我正在寻找关于如何处理正在创建的csv文件的建议,然后由我们的客户上传,并且可能在值中有逗号,如公司名称。

我们正在考虑的一些想法是:带引号的标识符(value "," values ","等等)或使用|代替逗号。最大的问题是我们必须让它变得简单,否则客户就不会这么做。


当前回答

在欧洲,我们有这个问题必须早于这个问题。在欧洲,我们用逗号来表示小数点。请看下面的数字:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

因此,CSV文件不能使用逗号分隔符。由于这个原因,欧洲的CSV文件由分号(;)分隔。

像微软Excel这样的程序可以读取带有分号的文件,也可以从分隔符切换到分号。您甚至可以使用制表符(\t)作为分隔符。请看来自Supper用户的回答。

其他回答

由于这是关于一般实践,让我们从经验法则开始:

不要使用CSV,而是使用带有库的XML来读写XML文件。 如果必须使用CSV。正确操作并使用免费库来解析和存储CSV文件。

为了证明1),大多数CSV解析器没有编码意识,所以如果你不处理US-ASCII,你是在自找麻烦。 例如,excel2002以本地编码存储CSV,而没有任何关于编码的说明。CSV标准没有被广泛采用:(。 另一方面,xml标准被很好地采用,它处理编码非常好。

为了证明2),几乎所有语言都有大量的csv解析器,所以即使解决方案看起来非常简单,也没有必要重新发明轮子。

举几个例子:

对于python使用构建CSV模块 为perl检查CPAN和文本::CSV 对于PHP,使用内置的fgetcsv/fputcsv函数 java检查SuperCVS库

实际上,如果你不打算在嵌入式设备上解析它,就没有必要手动实现它。

您可以在字段周围加上双引号。我不喜欢这种方法,因为它增加了另一个特殊字符(双引号)。只需定义一个转义字符(通常是反斜杠),并在需要转义的地方使用它:

data,more data,more data\, even,yet more

您不必尝试匹配引号,而且需要解析的异常也更少。这也简化了您的代码。

    public static IEnumerable<string> LineSplitter(this string line, char 
         separator, char skip = '"')
    {
        var fieldStart = 0;
        for (var i = 0; i < line.Length; i++)
        {
            if (line[i] == separator)
            {
                yield return line.Substring(fieldStart, i - fieldStart);
                fieldStart = i + 1;
            }
            else if (i == line.Length - 1)
            {
                yield return line.Substring(fieldStart, i - fieldStart + 1);
                fieldStart = i + 1;
            }

            if (line[i] == '"')
                for (i++; i < line.Length && line[i] != skip; i++) { }
        }

        if (line[line.Length - 1] == separator)
        {
            yield return string.Empty;
        }
    }

如果您对如何解析一般文件(以CSV为例)更有教育意义的练习感兴趣,您可以查看Julian Bucknall的这篇文章。我喜欢这篇文章,因为它把事情分解成更小的问题,这些问题不那么难以克服。首先创建一个语法,一旦您有了一个好的语法,将语法转换为代码是一个相对简单和有条理的过程。

本文使用c#,并在底部有一个下载代码的链接。

CSV格式使用逗号分隔值,包含回车、换行、逗号或双引号的值用双引号括起来。包含双引号的值会被引用,并且每个文字引号都被紧挨着的前引号转义:例如,以下3个值:

test
list, of, items
"go" he said

将被编码为:

test
"list, of, items"
"""go"" he said"

任何字段都可以加引号,但只有包含逗号、CR/NL或引号的字段必须加引号。

CSV格式没有真正的标准,但几乎所有应用程序都遵循这里记录的约定。在其他地方提到的RFC不是CSV的标准,它是一个用于在MIME中使用CSV的RFC,它包含了一些非常规的和不必要的限制,使它在MIME之外无用。

我所见过的许多CSV模块不适应的一个问题是,可以在单个字段中编码多行,这意味着您不能假设每一行都是一个单独的记录,您要么需要不允许数据中出现换行,要么准备好处理这个问题。