I have a CSV file, I am trying to replace 1st column details with 2nd column values using String.Replace in C#,This is working fine. But next when I try replacing 2nd column with 6th column values, it is affecting the 1st column values also..?
string[] lines = File.ReadAllLines(file);
for(int i=1;i<lines.Length;i++)
{
if (lines[i].Split(',')[1].Contains('.'))
{
lines[i] = lines[i].Replace(lines[i].Split(',')[0], lines[i].Split(',')[1]);
lines[i] = lines[i].Replace(lines[i].Split(',')[1], lines[i].Split(',')[6]);
}
}
File.WriteAllLines(file,lines);
There is a miss understanding of what lines[i].Replace does. If you click on it and press F12 or F1 you will see that it's actually String.Replace(String, String).
From the documentation: "Returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string."
In your code you want to move values from column 2 to column 1 etc. Not remplace the all occurence of the value of column 1.
for (int i = 1; i < lines.Length; i++)
{
// your if here.
var columns = lines[i].Split(',');
columns[0] = columns[1];
columns[1] = columns[5];
lines[i] = string.Join(",", columns);
}
In the following Live demo, I removed the if and emulate fileRead and Write with simple string [] and string.
Related
I have a DataGridView with TextBox colums. One of the columns display record counts which are formatted as ###,###,000. The column itself isn't set to format the text, but the data is formatted when the data source is populated. The data source is a List by the way. The DataGridView merely displays everything as it gets it.
Now, I need to parse the numeric text value into a variable, which is fine by doing
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString())
but, if I have numbers reaching thousands, it displays as 1 000, because of the formatting. The formatting generates a space rather than a comma as this is how the environment has been configured. When I try to parse that value, I get an exception because of the space in the numeric value.
I have tried formatting the string value
int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and
int.Parse(String.Format("{0:########0}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and all sorts of variants, but it keeps returning the space in the value, which then won't parse. I have tried replacing the space, but it is persistent. Also, the space shows ASCII keycode 63 which is supposed to be a question mark, not so? Even when I try to replace using the keycode... nothing!
Any ideas as to why this is happening and how to fix it?
The complete code block I have is
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
//-------------------------------------------------------------------------
// this is only to test and see what value I get for the space character, will be removed later
string test_str = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", string.Empty);
test_str = test_str.Replace(" ", "");
for (int k = 0; k < test_str.Length; k++)
{
string newstr = test_str.Substring(k, 1);
var kycode = ASCIIEncoding.ASCII.GetBytes(newstr);
}
//-------------------------------------------------------------------------
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
});
}
}
Use simple Solution:-
If space is available Remove it and then simply Parse into INT.
str.Replace(" ", String.Empty)
string data = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", String.Empty);
int.Parse(data);
Make it easier:-
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(" ", String.Empty));
And if you want to remove space and comma both while parsing using this Regular Expression
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(/[, ]+/g, " ").trim());
Check This Small Example First you will get Clear Idea:-
string data = "1 0000";
string result = data.Replace(" ", string.Empty);
Since the replace method didn't remove spaces as I expected to, I resorted to the below solution. This will also remove any other numeric separators irrespective of what the numeric separator has been set up as in the OS.
//get the numeric decimal seperator key code
string dummy_numeric = (1000).ToString(Helper.application_number_display_format);
char replace_char = (char)0;
foreach (char current_char in dummy_numeric)
{
if (!System.Char.IsDigit(current_char))
{
replace_char = current_char;
break;
}
}
//get all the files that are selected for migration
List<Migrate> migrate = new List<Migrate>();
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(replace_char.ToString(), ""))
});
}
}
I try to create a csv file in c#. First I wrote a little piece of code to test. I saw on that post that the "," character is use to create different columns but it doesn't work for me.
I searched on different topic but all answer are something like String.Format("{0},{1}", first, second);
My code :
String first = "Test name";
String second = "Value";
String newLine = String.Format("{0},{1}", first, second);
csv.AppendLine(newLine);
for (int i = 0; i < 3; i++)
{
first = "Test_" + i;
second = i.ToString();
newLine = String.Format("{0},{1}", first, second);
csv.AppendLine(newLine);
}
System.IO.File.WriteAllText(path, csv.ToString());
This create rightly the lines but all in column 1
Assuming csv to be a StringBuilder, this should create the file
Test name,Value
Test_0,0
Test_1,1
Test_2,2
which is a valid CSV file with two columns and three rows (and headers).
Are you by any chance using a non-English locale (specifically, one that uses the comma as a decimal separator) and trying to load the CSV in Excel? In that case Excel assumes ; as the field separator instead of ,. You can split the data with custom settings if needed (I believe the feature is called “Text to fields”, or “Text to columns” on the Data tab in the ribbon).
I am creating a GUI that outputs raw serial data onto a textbox, and I want the user to be able to choose certain columns from that data to print onto a label next to the text box every time the data updates. I can do this when there is only one column chosen, however, when I try to add multiple columns, I get the error "Cannot Explicitly Convert string[] to string". How can I take multiple columns of data, put them into one string, then print the string to the label?
Here is what I have done so far:
string[] data_disp = new string[10];
string[] blahArray = line.Split(new char[] { ',' });
int count1 = txt_PRINT_COLUMN_2.Text.Split(',').Length - 1;
string[] countarr = txt_PRINT_COLUMN_2.Text.Split(new char[] { ',' });
for (int i = 0; i <= count1;)
{
int column_data = Convert.ToInt32(countarr[i]);
double inst2 = Convert.ToDouble(blahArray[column_data]);
data_disp[i] = Convert.ToString(inst2);
i++;
}
lbl_SHOW_COLUMN_2.Text = String.Join(",",data_disp);
"line" is the incoming data, txt_PRINT_COLUMN_2 is the textbox where the user enters the desired columns, and lbl_SHOW_COLUMN_2 is the label where the data should print.
EDIT: I used string.join which takes care of the string error, however, the string data_disp is still null. How do I fill it in with the values?
EDIT2: I added i++ to the for loop and made the condition for i <= count1. This worked for the first iteration, however, when the data updated, I got the error: "Input string was not in the correct format" on the line inst2. How do I fix this?
i am trying to create a data table from a tab delimited text file.I am getting the values from the file easily.The problem is that when there is a empty column in text file same empty column is not created in data table instead the next non-empty column contents get replaced in the empty columns area
format of data in textfile
id name product cost company name
1 abc shoe xxx
2 xyz chain yyy
Data table obtained
id name product cost company name
1 abc shoe xxx
2 xyz chain yyy
my code to getdata
var reader = new StreamReader(File.OpenRead(#"d:\d.txt"));
var table = new DataTable("SampleTable");
string[] fieldValues = reader.ReadLine().Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < fieldValues.Length; i++)
{
table.Columns.Add(new DataColumn(fieldValues[i].ToString().Trim()));
}
while (!reader.EndOfStream)
{
var line = reader.ReadLine().Trim();
var values = line.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
string[] ee = values;
var newRow = table.NewRow();
for (int i = 0; i < ee.Length; i++)
{
newRow[i] = ee[i].Trim().ToString(); // like sample [0,0]
}
table.Rows.Add(newRow);
}
You told Split to do exactly what you observe by setting the option StringSplitOptions.RemoveEmptyEntries - it removes empty entries.
Remove this option and it will keep the empty column.
The problem might be that you split the line with the RemoveEmptyEntries option:
var values = line.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
The empty cell gets removed. Omit this parameter and it should work...
If you have an empty column, then you should read an empty string, not a null string.
In other words....
1,abc,shoe,,xxx
The reason your getting the result your getting is because of this: StringSplitOptions.RemoveEmptyEntries
ArrayList fileList = new ArrayList();
private void button2_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string line;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(openFileDialog1.FileName);
while ((line = file.ReadLine()) != null)
{
// Puts elements in table
fileList.Add(line.Split(';'));
}
file.Close();
}
for (int i = 0; i < fileList.Count; i++)
{
for (int x = 0; x < (fileList[i] as string[]).Length; x++)
{
// if (x ==0)
// {
//fileList[0] must Be int
// }
// if (x==1)
//fileList[1] must be string
this.textBox2.Text += ((fileList[i] as string[])[x] + " ");
}
this.textBox2.Text += Environment.NewLine;
}
}
I am so far here.
I take the elements from a CSV file.
I need now to be sure that the 1 column has only numbers-integers (1,2,3,4,5), the second column has only names(so it will have the type string or character), the third surnames etc. etc.
The rows are presented like this : 1;George;Mano;
How can I be sure that the CSV file has the correct types?
I think that any more code about this problem will be placed inside the 2 for statements.
Thank you very much,
George.
I think your question needs more work.
You don't show your declaration for filelist. Whatever it is, there is no reason to convert it to string[] just to get the length. The length with be the same no matter what type it is. You cannot use this method to determine which items are strings.
You'll need to loop through the items and see if they contain only digits or whatever.
Also, your code to read CSV files is not quote right. CSV files are comma-separated. And it's possible that they could contain commas within double quotes. These commas should be ignored. A better way to read CSV files can be seen here.
An Arraylist contains object.
System.IO.StreamReader.ReadLine returns a String.
Checking the value of the first line read and trying to convert the string into an integer would be a valid approach.
Your current approach is adding the String that is returned by System.IO.StreamReader.ReadLine into your collection which you later turn into a String[] by using the String.Split method.
Your other requirements will be a greal more difficult because every line you are reading is a String already. So you would have to look at each character within the string to determine if it appears to be a name.
In other words you might want to find a different way to provide an input. I would agree that a regular expression might be the best way to get rid of junk data.
Edit: Now that we know it's really CSV, here's a columnar answer ;-)
Your ArrayList contains string[], so you need to verify that each array has the appropriate type of string.
for (int i = 0; i < fileList.Count; i++)
{
string[] lineItems = (string[])fileList[i];
if (!Regex.IsMatch (lineItems[0], "^\d+$")) // numbers
throw new ArgumentException ("invalid id at row " + i);
if (!Regex.IsMatch (lineItems[1], "^[a-zA-Z]+$")) // surnames - letters-only
throw new ArgumentException ("invalid surname at row " + i);
if (!Regex.IsMatch (lineItems[2], "^[a-zA-Z]+$")) // names - letters-only
throw new ArgumentException ("invalid name at row " + i);
}
You can use Regex class.
fileList[0] must Be int:
int x;
if(int.TryParse(fileList[0], out x)){ //do whatever here and x will have that integer value. TryParse will return false if it's not an integer so the if will not fire}
fileList[1] must be string :
iterate over the string and check each element is a letter. look at the char. methods for the appropriate one.