2016-01-11 475 views
3

如果此问题重复,请道歉。CSV解析包含双引号和逗号的字符串

我试图创建一个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); 

本来我采取了上述方法,但很快遇到了问题,如果从数据库中读取的任何字段中有逗号,那么该字段将在中间被分割,例如如果评论=“评论,去,这里”将分布在CSV列中的3列而不是1.

为了尝试和克服这个问题,我改变了我的代码,以便所有字段都用双引号括起来,意思是逗号字段内将不再分裂CSV,如下所示:

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

现在,这地方,我得到了一个问题,如果任何值从数据库中读取包含双引号,这会混淆一切,因为数据库中的双引号显示为“当字段转换为字符串时,这就是我已经用来将每个字段的开始和结尾用双引号括起来以防止逗号分割包含的字段逗号。

回答

3

您需要转义双引号。你逃脱它们的方式取决于你计划阅读的任何内容。有可能转义序列应该是一个反斜杠,后跟一个双引号,但是如果使用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("\"", "\"\"")); 
+0

接受这个作为答案,因为这正是我一直在寻找它最简单的形式 - 尽管梅德也做提供一个很好的解我希望我能接受两个。 – axel

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

你加倍的是来自于数据库中的任何现有的双引号,所以他们视为被包含在场内(列)而不是表示一个字段的开始或结束。

看到这个答案对于包含字段中同时双引号和逗号CSV的例子: https://stackoverflow.com/a/12473481/1184850

相关问题