【问题标题】:Parsing .csv file into 2d array将 .csv 文件解析为二维数组
【发布时间】:2013-09-14 21:51:50
【问题描述】:

我正在尝试将 CSV 文件解析为 C# 中的二维数组。我遇到了一个非常奇怪的问题,这是我的代码:

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 行读入数据数组,但是当它第 16 次下降到 data[Row, column] = Line[column]; 行时它似乎只是跳出整个循环(不满足sr.EndOfStream 条件)并且不再将任何数据读入数据数组。

谁能解释一下可能发生的事情?

【问题讨论】:

  • 每行的列数是否相同?列数是否等于行数?您正在将数组中的总行数初始化为 csv 第一行中的列数。
  • 我以为你的 csv 文件中有一些特殊的字符。首先从 csv 中删除前 15 行,然后将其上传。如果遇到同样的错误,请回复
  • 我删除了第 16 行,同样的事情发生了,我删除了第 15 行周围的几行,同样的事情发生了。它似乎只能读取 15 行代码,但现在解释了为什么以及实际上代码永远不会离开 while 循环并且之后不会执行任何操作。这是我在编程中遇到的最奇怪的事情。
  • @MattR 有 87 行,并非所有行都有相同数量的列,但是对于前 15 行,它只是完全按照预期用空白值填充空格,所以我不认为这是问题
  • 第16行的列数比第一行大吗?

标签: c# csv


【解决方案1】:

上述代码的更短版本:

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 documentation 中对较大的文件更有效:

当你使用ReadLines时,你可以在整个集合返回之前开始枚举字符串集合;使用 ReadAllLines 时,必须等待返回整个字符串数组才能访问该数组。因此,当您处理非常大的文件时,ReadLines 会更有效率。

【讨论】:

  • 但是由于我们立即转换为数组,所以在这里没有任何区别。
  • 此解决方案与 Khan 的问题相同。如果 x.Split() 包含逗号,它将拆分单元格数据。
【解决方案2】:

您的代码中没有任何内容可以及时从文件中获取行数以供使用。

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();

【讨论】:

  • 这不是一个可靠的解决方案。假设您有以下数据:1、2,“您看,这是文本。” .Split() 的输出将包含 5 个项目而不是 3 个。
  • 取决于数据。如果您知道它正在处理的数据不会包含逗号,那么这样做应该没问题。
  • 我总是将我的 CSV 默认值更改为管道“|”因此,分隔文件格式。
  • 这不适用于带有逗号的单元格,例如:data1,data2,data3,"data,with,comma",data5
【解决方案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);
                 }
      
      
              }
      

      【讨论】:

        猜你喜欢
        • 2012-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-19
        • 1970-01-01
        相关资源
        最近更新 更多