【问题标题】:Split does not work as expected with commas使用逗号拆分无法按预期工作
【发布时间】:2018-03-12 14:14:26
【问题描述】:

我需要编写一个 CSV 解析器,我现在正试图分离字段来操作它们。

CSV 示例: mitarbeiter^tagesdatum^lohnart^kostenstelle^kostentraeger^menge^betrag^belegnummer 11005^23.01.2018^1^^31810020^5,00^^ 11081^23.01.2018^1^^31810020^5,00^^

如您所见,有几个空单元格。

我正在做以下事情:

 using (CsvFileReader reader = new CsvFileReader(path))
        {
            CsvRow row = new CsvRow();                
            while (reader.ReadRow(row))
            {
                foreach (string s in row)
                {
                    csvROW.Add(new aCSVROW());
                    string[] items = s.Split(new char[] { '^' }, StringSplitOptions.None);
                    csvROW[0].mitarbeiter = items[0];
                    csvROW[0].tagesdatum = items[1];
                    csvROW[0].lohnart = items[2];
                    csvROW[0].kostenstelle = items[3];
                    csvROW[0].kostentraeger = items[4];
                    csvROW[0].menge = items[5];
                    csvROW[0].betrag = items[6];
                    csvROW[0].belegnummer = items[7];
                }                   
            }
        }

问题:

Split 似乎在逗号 (5,00) 之后停止。分隔符是^ ...有什么原因吗? 我尝试了几件事都没有成功......

非常感谢!

【问题讨论】:

  • 是否可以 CsvRow.ReadRow 以逗号分隔,因为它假设为 csv?
  • 看起来它在, 上拆分字段,然后您将第一个字段拆分在^ 上,第二个s in row 可能会得到您00^^ 11081^23.01.2018^1^^31810020^5
  • 是一行还是二行?只有 5 个单词.. 所以如果 csv 拆分器将这些作为标题,它将解释为什么它只得到 5 个值
  • 在我的机器上运行良好
  • @DavinTryon:谢谢!这可以解决问题......我正在尝试修复它并会给你反馈。更新:Jup,ReadRow 以逗号分隔...非常感谢!

标签: c# csv split


【解决方案1】:

CsvFileReader 从 CSV 文件中读取行,然后读取该行中的字符串。除了分隔行之外,您还期望CsvFileReader 做什么?

读完第二行,row会有内容

11005^23.01.2018^1^^31810020^5

和

00^^ 

当您将第一行除以^ 时,结果数组的最后一个条目将是"5"。无论如何,您的代码会抛出异常,因为您试图访问超出数组边界的项目。

我不知道CsvFileReader。也许您可以将^ 作为分隔符传递,而不必拆分字符串。无论如何,您也可以使用StreamReader。这将更符合您的预期。

using (StreamReader reader = new StreamReader(path))
{              
    while (!reader.EndOfStream)
    {
        var csvLine = reader.ReadLine();
        csvROW.Add(new aCSVROW());
        string[] items = csvLine.Split(new char[] { '^' }, StringSplitOptions.None);
        csvROW[0].mitarbeiter = items[0];
        csvROW[0].tagesdatum = items[1];
        csvROW[0].lohnart = items[2];
        csvROW[0].kostenstelle = items[3];
        csvROW[0].kostentraeger = items[4];
        csvROW[0].menge = items[5];
        csvROW[0].betrag = items[6];
        csvROW[0].belegnummer = items[7];
    }                   
}

【讨论】:

    【解决方案2】:

    CsvRow 是所有行的数据,还是一个行的数据?因为事实上,您不断为每个读取行添加一个新的aCSVROW 对象到csvROW,但您不断替换 csvROW[0] 上的 data,first em> 插入aCSVROW。这意味着最后,您将有很多行中都没有数据,除了索引 0 上的行,它的属性在每次迭代时都被覆盖,并最终包含最后读取行的数据.

    此外,尽管使用了 CsvReader 类,但您使用普通的 String.Split 来实际分隔字段。确定这就是 CsvReader 类的用途吗?

    就我个人而言,我总是使用来自Microsoft.VisualBasic.FileIO 命名空间的TextFieldParser。它的优点是它在 .Net 框架中完全原生,您可以简单地告诉它使用哪个分隔符。

    这个函数可以很简单的把数据取出来List<String[]>:

    A: Using C# to search a CSV file and pull the value in the column next to it

    获得数据后,您可以随意将其粘贴到对象中。

    List<String[]> lines = SplitFile(path, textEncoding, "^");
    // I assume "CsvRow" is some kind of container for multiple rows?
    // Looks like pretty bad naming to me...
    CsvRow allRows = new CsvRow();
    foreach (String items in lines)
    {
        // Create new object, and add it to list.
        aCSVROW row = new aCSVROW();
        csvROW.Add(row);
        // Fill the actual newly created object, not the first object in allRows.
        // conside adding index checks here though to avoid index out of range exceptions.
        row.mitarbeiter = items[0];
        row.tagesdatum = items[1];
        row.lohnart = items[2];
        row.kostenstelle = items[3];
        row.kostentraeger = items[4];
        row.menge = items[5];
        row.betrag = items[6];
        row.belegnummer = items[7];
    }
    // Done. All rows added to allRows.
    

    【讨论】:

      【解决方案3】:
       CsvRow row = new CsvRow();                
                  while (reader.ReadRow(row))
                  {
                      foreach (string s in row)
                      {
                          csvROW.Add(new aCSVROW());
                          s.Split("^","");
      csvROW[0].mitarbeiter = items[0];
                          csvROW[0].tagesdatum = items[1];
                          csvROW[0].lohnart = items[2];
                          csvROW[0].kostenstelle = items[3];
                          csvROW[0].kostentraeger = items[4];
                          csvROW[0].menge = items[5];
                          csvROW[0].betrag = items[6];
                          csvROW[0].belegnummer = items[7];
                      }                   
                  }
              }
      

      【讨论】:

      • 一个好的答案将解释它在做什么,而不仅仅是提供裸代码。此外,您更改的只是对 Split 的调用(本身不太可能是问题),但您从未分配 items(您在下一行中引用)。所以这甚至不会编译。
      猜你喜欢
      • 1970-01-01
      • 2018-01-08
      • 2016-05-20
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 2018-10-06
      相关资源
      最近更新 更多