CSV字符串处理

Chr*_*lid 20 c# csv

创建CSV字符串的典型方法(伪代码):

  1. 创建一个CSV容器对象(如C#中的StringBuilder).
  2. 循环遍历要添加的字符串,在每个字符串后面添加逗号.
  3. 循环之后,删除最后一个多余的逗号.

代码示例:

public string ReturnAsCSV(ContactList contactList)
{
    StringBuilder sb = new StringBuilder();
    foreach (Contact c in contactList)
    {
        sb.Append(c.Name + ",");
    }

    sb.Remove(sb.Length - 1, 1);
    //sb.Replace(",", "", sb.Length - 1, 1)

    return sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)

我喜欢通过检查容器是否为空来添加逗号的想法,但这是否意味着更多的处理,因为它需要在每次出现时检查字符串的长度?

我觉得应该有一个更简单/更清洁/更有效的方法来删除最后一个逗号.有任何想法吗?

Dav*_*ier 21

您可以使用LINQ to Objects:

string [] strings = contactList.Select(c => c.Name).ToArray();
string csv = string.Join(",", strings);
Run Code Online (Sandbox Code Playgroud)

显然,这一切都可以在一条线上完成,但两条线路更清晰一些.

  • 不太明显的是它实际上并没有实现CSV规范.这是将逗号放入字符串的好方法,但这与CSV格式不同. (4认同)

dbk*_*bkk 9

您的代码不完全符合完整的CSV格式.如果您只是从没有逗号,前导/尾随空格,制表符,换行符或引号的数据生成CSV,那么应该没问题.但是,在大多数现实世界的数据交换方案中,您确实需要完整的实现.

要生成适当的CSV,您可以使用:

public static String EncodeCsvLine(params String[] fields)
{
    StringBuilder line = new StringBuilder();

    for (int i = 0; i < fields.Length; i++)
    {
        if (i > 0)
        {
            line.Append(DelimiterChar);
        }

        String csvField = EncodeCsvField(fields[i]);
        line.Append(csvField);
    }

    return line.ToString();
}

static String EncodeCsvField(String field)
{
    StringBuilder sb = new StringBuilder();
    sb.Append(field);

    // Some fields with special characters must be embedded in double quotes
    bool embedInQuotes = false;

    // Embed in quotes to preserve leading/tralining whitespace
    if (sb.Length > 0 && 
        (sb[0] == ' ' || 
         sb[0] == '\t' ||
         sb[sb.Length-1] == ' ' || 
         sb[sb.Length-1] == '\t' ))
    {
        embedInQuotes = true;
    }

    for (int i = 0; i < sb.Length; i++)
    {
        // Embed in quotes to preserve: commas, line-breaks etc.
        if (sb[i] == DelimiterChar || 
            sb[i]=='\r' || 
            sb[i]=='\n' || 
            sb[i] == '"') 
        { 
            embedInQuotes = true;
            break;
        }
    }

    // If the field itself has quotes, they must each be represented 
    // by a pair of consecutive quotes.
    sb.Replace("\"", "\"\"");

    String rv = sb.ToString();

    if (embedInQuotes)
    {
        rv = "\"" + rv + "\"";
    }

    return rv;
}
Run Code Online (Sandbox Code Playgroud)

可能不是世界上最有效的代码,但它已经过测试.与快速示例代码相比,真实世界很糟糕:)


Mat*_*ton 5

别忘了我们的老朋友"为了".它并不像foreach那样美观,但它具有能够从第二个元素开始的优势.

public string ReturnAsCSV(ContactList contactList)
{
    if (contactList == null || contactList.Count == 0)
        return string.Empty;

    StringBuilder sb = new StringBuilder(contactList[0].Name);

    for (int i = 1; i < contactList.Count; i++)
    {
        sb.Append(",");
        sb.Append(contactList[i].Name);
    }

    return sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)

您还可以将第二个Append包装在"if"中,以测试Name属性是包含双引号还是逗号,如果是,则适当地转义它们.


小智 5

为什么不使用其中一个开源CSV库?

我知道这听起来有些过于简单,但正如你可以从评论和代码片段中看到的那样,不仅仅是满足于眼睛.除了处理完整的CSV合规性之外,您最终还是要处理读取和写入CSV ...并且您可能需要文件操作.

我之前在我的一个项目中使用过Open CSV(但还有很多其他项目可供选择).这当然让我的生活更轻松.;)