【问题标题】:How to properly split a CSV using C# split() function?如何使用 C# split() 函数正确拆分 CSV?
【发布时间】:2013-06-16 22:24:40
【问题描述】:

假设我有这个 CSV 文件:

NAME,ADDRESS,DATE
"Eko S. Wibowo", "Tamanan, Banguntapan, Bantul, DIY", "6/27/1979"

我想将使用双引号括起来的每个标记存储在一个数组中,是否可以安全地执行此操作而不是使用 String split() 函数?目前我在 RichTextBox 中加载文件,然后使用它的 Lines[] 属性,我为每个 Lines[] 元素执行一个循环并执行此操作:

string[] line = s.Split(',');

s 是对 RichTextBox.Lines[] 的引用。 正如您可以清楚地看到的那样,标记内的逗号很容易弄乱 split() 函数。所以,我没有以我想要的三个令牌结束,而是以 6 个令牌结束

任何帮助将不胜感激!

【问题讨论】:

标签: c#


【解决方案1】:

你也可以使用正则表达式:

string input = "\"Eko S. Wibowo\", \"Tamanan, Banguntapan, Bantul, DIY\", \"6/27/1979\"";
string pattern = @"""\s*,\s*""";

// input.Substring(1, input.Length - 2) removes the first and last " from the string
string[] tokens = System.Text.RegularExpressions.Regex.Split(
    input.Substring(1, input.Length - 2), pattern);

这会给你:

Eko S. Wibowo
Tamanan, Banguntapan, Bantul, DIY
6/27/1979

【讨论】:

  • 我接受了这个作为答案,因为我一直想提高我在 RegEx 上的技能,实际上,这个解决方案应该是 PHP 解决方案的一部分,这也很大程度上依赖于 RegEx。仅使用 .NET 解决方案不是一个好主意。虽然,我很抱歉我没有足够详细地说明它。当我阅读@unlimit 的答案时,我刚刚想到了这个想法:一个简单的正则表达式就是要走的路!
  • 这是一个很好的解决方案,但请注意并非每个 CSV 文件都会总是在每个值周围加上引号。我知道如果你从 Excel 制作一个 CSV 文件,它不会,只有当值在值中包含逗号、引号等时。
  • 更好的模式是""?\s*,\s*""?,这样它也匹配没有双引号的列。有时 CSV 文件的数值不带双引号。
【解决方案2】:

我已经用我自己的方法做到了。它只计算"' 字符的数量。
根据您的需要进行改进。

    public List<string> SplitCsvLine(string s) {
        int i;
        int a = 0;
        int count = 0;
        List<string> str = new List<string>();
        for (i = 0; i < s.Length; i++) {
            switch (s[i]) {
                case ',':
                    if ((count & 1) == 0) {
                        str.Add(s.Substring(a, i - a));
                        a = i + 1;
                    }
                    break;
                case '"':
                case '\'': count++; break;
            }
        }
        str.Add(s.Substring(a));
        return str;
    }

【讨论】:

  • 通过在计数器中同时包含 "',您将错误地解析带有混合引号的内容:" \"The quote's break\", this "
  • @drzaus:没错。实际的方法更复杂,并且有很多针对不同事物的计数器。显示的代码旨在显示基本思想。
【解决方案3】:

这不是您问题的确切答案,但是您为什么不使用已经编写的库来操作 CSV 文件,很好的例子是LinqToCsv。 CSV 可以用各种标点符号分隔。此外,还有一些问题,图书馆创建者已经解决了这些问题。比如处理名称行、处理不同的日期格式以及将行映射到 C# 对象。

【讨论】:

    【解决方案4】:

    您可以将"," 替换为;,然后用; 拆分

    var values= s.Replace("\",\"",";").Split(';');
    

    【讨论】:

      【解决方案5】:

      如果您的 CSV 行紧凑,最简单的方法是使用前面提到的结束和尾部删除,然后在连接字符串上进行简单拆分

       string[] tokens = input.Substring(1, input.Length - 2).Split("\",\"");
      

      这只有在所有字段都被双引号引起来时才有效,即使它们(官方)不需要。它会比 RegEx 更快,但在特定条件下使用。

      如果您的数据看起来像 "姓名","1","12/03/2018","Add1,Add2,Add3","其他东西"

      【讨论】:

        【解决方案6】:

        5 岁了,但总有人想要拆分 CSV。

        如果您的数据简单且可预测(即从不包含任何特殊字符,如逗号、引号和换行符),那么您可以使用 split() 或正则表达式来完成。

        但要在不使用代码汤的情况下正确支持 CSV 格式的所有细微差别,您应该真正使用已经发现所有魔力的库。不要重新发明轮子(当然,除非你这样做是为了好玩)。

        CsvHelper 使用起来非常简单:

        https://joshclose.github.io/CsvHelper/2.x/

        using (var parser = new CsvParser(textReader)
        {
            while(true)
            {
                string[] line = parser.Read();
        
                if (line != null)
                {
                    // do something
                }
                else
                {
                    break;
                }
            }
        }
        

        更多讨论/相同问题: Dealing with commas in a CSV file

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-29
          • 2022-01-19
          • 2013-10-28
          • 1970-01-01
          相关资源
          最近更新 更多