Reputation:
I'm trying to parse a CSV file into a 2D array in C#. I'm having a very strange issue, here is my code:
string filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
StreamReader sr = new StreamReader(filePath);
data = null;
int Row = 0;
while (!sr.EndOfStream)
{
string[] Line = sr.ReadLine().Split(',');
if (Row == 0)
{
data = new string[Line.Length, Line.Length];
}
for (int column = 0; column < Line.Length; column++)
{
data[Row, column] = Line[column];
}
Row++;
Console.WriteLine(Row);
}
My .csv file has 87 rows, but there is a strange issue in the execution where it will read the first 15 rows into the data array exactly as expected but when it gets down to the data[Row, column] = Line[column];
line for the 16th time it seems to just break out of the entire loop (without meeting the sr.EndOfStream
condition) and not read any more data into the data array.
Can anyone explain what might be happening?
Upvotes: 12
Views: 44879
Reputation: 1
With Open File Dialog
OpenFileDialog opn = new OpenFileDialog();
if (opn.ShowDialog() == DialogResult.OK)
{
StreamReader sr = new StreamReader(opn.FileName);
List<string[]> data = new List<string[]>();
int Row = 0;
while (!sr.EndOfStream)
{
string[] Line = sr.ReadLine().Split(',');
data.Add(Line);
Row++;
Console.WriteLine(Row);
}
}
Upvotes: 0
Reputation: 337
This is the same as posted by Pavel, but it ignores empty lines that may cause your program to crash.
var filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
string[][] data = File.ReadLines(filepath).Where(line => line != "").Select(x => x.Split('|')).ToArray();
Upvotes: 4
Reputation: 6971
A shorter version of the code above:
var filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
var data = File.ReadLines(filePath).Select(x => x.Split(',')).ToArray();
Note the user of ReadLines
instead of ReadAllLines
, which is more efficient on larger files as per MSDN documentation:
When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.
Upvotes: 17
Reputation: 12170
Without knowing the contents of your csv file, I would assume that the error is generated by this line:
if (Row == 0)
{
data = new string[Line.Length, Line.Length];
}
By initialising the total amount of rows to the amount of columns in the first line of the csv, you are assuming that the amount of rows is always equal to the amount of columns.
As soon as the amount of rows is greater than the total columns of the first line of the csv, you are going to overrun the data
array by attempting to access a row that isn't there.
You can simplify your code by changing your data
to be a list to allow for dynamic adding of items:
string filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
StreamReader sr = new StreamReader(filePath);
List<string> data = new List<string[]>();
int Row = 0;
while (!sr.EndOfStream)
{
string[] Line = sr.ReadLine().Split(',');
data.Add(Line);
Row++;
Console.WriteLine(Row);
}
Upvotes: 0
Reputation: 18142
Nothing in your code gets the number of lines out of your file in time to use it.
Line.Length
represents the number of columns in your csv, but it looks like you're also trying to use it to specify the number of lines in your file.
This should get you your expected result:
string filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
StreamReader sr = new StreamReader(filePath);
var lines = new List<string[]>();
int Row = 0;
while (!sr.EndOfStream)
{
string[] Line = sr.ReadLine().Split(',');
lines.Add(Line);
Row++;
Console.WriteLine(Row);
}
var data = lines.ToArray();
Upvotes: 12