CSV解析包含双引号和逗号的字符串

时间:2016-01-11 12:42:19

标签: c# csv formatting string-formatting

如果此问题重复,请道歉。

我正在尝试创建一个CSV文件,例如,标题,名称和注释列。 CSV的每一行都有将每个列的值从数据库读入相关变量,然后将这些变量(用逗号分隔)添加到变量“newline”中,然后将其附加到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);

最初我采用了上述方法,但很快遇到了这样的问题,即如果从数据库中读入的任何字段中都有逗号,则该字段将在中间分割,例如if comments =“Comment,go,here”将分布在out CSV中的3列而不是1。

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

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

现在,有了这个,我遇到一个问题,如果从数据库中读入的任何值包含双引号,这会弄乱一切,因为数据库中的双引号显示为“字段被转换为字符串,这是我用来用双引号包装每个字段的开头和结尾以防止逗号分割包含逗号的字段。

3 个答案:

答案 0 :(得分:4)

你需要逃避双引号。你逃脱它们取决于你打算用它们读什么。转义序列应该是反斜杠后跟双引号,但如果使用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("\"", "\"\""));

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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

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