【问题标题】:CSV Parsing Strings containing double quotes and commasCSV 解析包含双引号和逗号的字符串
【发布时间】:2016-04-15 18:44:54
【问题描述】:

如果此问题重复,我们深表歉意。

我正在尝试创建一个包含标题、名称和评论列的 CSV 文件。 CSV 的每一行都有从数据库中读取到相关变量中的每一列的值,这些变量以逗号分隔,然后添加到变量“换行符”,然后将其附加到 csv,如下所示:

    string title = reader[0]
    string name = reader[1]
    string comments = reader[2]
    var csv = new StringBuilder();
    var headerLine = "Title,Name,Comments"
    csv.AppendLine(headerLine);

    var newline = title + "," + name + "," + comments;
    csv.AppendLine(newline);

最初我采用上述方法,但很快遇到了问题,如果从数据库中读取的任何字段中包含逗号,则该字段将在中间拆分,例如如果 cmets = "Comment, gos, here" 将分布在输出 CSV 中的 3 列而不是 1 列。

为了尝试解决这个问题,我更改了我的代码,以便所有字段都用双引号括起来,这意味着字段中的逗号将不再拆分 CSV,如下所示:

    var newline = "\"" + title + "\",\"" + name + "\",\"" + comments + "\""

现在,有了这个,我遇到了一个问题,如果从数据库中读取的任何值包含双引号,这会搞砸一切,因为数据库中的双引号显示为 \" 当字段被转换成一个字符串,这是我已经用来将每个字段的开头和结尾用双引号引起来的,以防止逗号拆分包含逗号的字段。

【问题讨论】:

    标签: c# csv formatting string-formatting


    【解决方案1】:

    您需要转义双引号。你用什么来逃避它们取决于你打算用什么来阅读它们。转义序列可能应该是反斜杠后跟双引号,但如果使用 Excel,它将是连续的两个双引号。这可以使用string.Replace 来完成。

    var newline = "\"" + title.Replace("\"", "\"\"") + 
                  "\",\"" + name.Replace("\"", "\"\"") + 
                  "\",\"" + comments.Replace("\"", "\"\"") + "\"";
    

    或使用string.Format

    var newline = string.Format(
        "\"{0}\",\"{1}\",\"{2}\"",
        title.Replace("\"", "\"\""),
        name.Replace("\"", "\"\""),
        comments.Replace("\"", "\"\""));
    

    【讨论】:

    • 接受这个作为答案,因为这正是我正在寻找的最简单的形式——尽管 Dmitry 也提供了一个很好的解决方案。我希望我能同时接受。
    【解决方案2】:

    规则很简单:如果项目包含,(逗号)或"(引号),则应将其放在引号中;项目中的每个" 都应该加倍:

      abcde    -> abcde        // or "abcde", quotation is not mandatory, however
      abc,de   -> "abc,de"
      abc"de   -> "abc""de"
      abc","de -> "abc"",""de"
    

    可能的实现:

        public static String EncodeCsvItem(String value) {
          if (String.IsNullOrEmpty(value))
            return "";
    
          StringBuilder Sb = new StringBuilder(value.Length + 2);
    
          bool wrap = false;
    
          foreach (var ch in value) {
            if (ch == '"') {
              Sb.Append('"');
              wrap = true;
            }
            else if (ch == ',')
              wrap = true;
    
            Sb.Append(ch);
          }
    
          if (wrap) {
            Sb.Insert(0, '"');
            Sb.Append('"');
          }
    
          return Sb.ToString();
        }
    
    ....
    
       var newline = String.Join(",",
         EncodeCsvItem(reader[0]),
         EncodeCsvItem(reader[1]),
         EncodeCsvItem(reader[2]) 
       );
    
       csv.AppendLine(newline);
    

    【讨论】:

      【解决方案3】:

      您将来自数据库的任何现有双引号加倍,因此它们被视为包含在字段(列)中,而不是表示字段的开头或结尾。

      有关在字段中包含双引号和逗号的 CSV 示例,请参阅此答案: https://stackoverflow.com/a/12473481/1184850

      【讨论】:

        猜你喜欢
        • 2018-03-20
        • 2020-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 2020-06-09
        相关资源
        最近更新 更多