Разбор CSV файла в 2d-массив
Я пытаюсь разобрать CSV файл в 2D-массив на С#. У меня очень странная проблема, вот мой код:
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);
}
Мой .csv файл имеет 87 строк, но в выполнении есть странная проблема, в которой он будет считывать первые 15 строк в массиве данных точно так, как ожидалось, но когда он приближается к строке data[Row, column] = Line[column];
в 16-й раз он просто вырывается из всего цикла (не удовлетворяя условию sr.EndOfStream
) и не читает больше данных в массиве данных.
Может кто-нибудь объяснить, что может произойти?
Ответы
Ответ 1
Ничто в вашем коде не забирает количество строк из вашего файла, чтобы использовать его.
Line.Length
представляет количество столбцов в вашем csv, но похоже, что вы также пытаетесь использовать его для указания количества строк в вашем файле.
Это даст вам ожидаемый результат:
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();
Ответ 2
Более короткая версия приведенного выше кода:
var filePath = @"C:\Users\Matt\Desktop\Eve Spread Sheet\Auto-Manufacture.csv";
var data = File.ReadLines(filePath).Select(x => x.Split(',')).ToArray();
Обратите внимание на пользователя ReadLines
вместо ReadAllLines
, что более эффективно для больших файлов согласно Документация MSDN:
Когда вы используете ReadLines, вы можете начать перечисление коллекции строк перед возвратом всей коллекции; когда вы используете ReadAllLines, вы должны дождаться возврата всего массива строк до того, как вы сможете получить доступ к массиву. Поэтому, когда вы работаете с очень большими файлами, ReadLines может быть более эффективным.
Ответ 3
Это то же самое, что и Pavel, но игнорирует пустые строки, которые могут привести к сбою вашей программы.
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();
Ответ 4
Не зная содержимого вашего CSV файла, я бы предположил, что эта ошибка генерируется этой строкой:
if (Row == 0)
{
data = new string[Line.Length, Line.Length];
}
Инициализируя общее количество строк на количество столбцов в первой строке csv, вы предполагаете, что количество строк всегда равно количеству столбцов.
Как только количество строк больше, чем полные столбцы первой строки csv, вы собираетесь перехватить массив data
, пытаясь получить доступ к строке, которая там не существует.
Вы можете упростить свой код, изменив data
на список, чтобы можно было динамически добавлять элементы:
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);
}
Ответ 5
С помощью диалогового окна "Открыть файл"
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);
}
}