【问题标题】:Quotes in tab-delimited file制表符分隔文件中的引号
【发布时间】:2011-01-26 09:59:48
【问题描述】:

我有一个简单的应用程序,它打开一个制表符分隔的文本文件,并将该数据插入数据库。

我正在使用这个 CSV 阅读器来读取数据:http://www.codeproject.com/KB/database/CsvReader.aspx

而且一切正常!

现在我的客户在文件末尾添加了一个新字段,即“ClaimDescription”,并且在其中一些索赔描述中,数据中包含引号,例如:

“SUMISEI MARU NO 2”-日本海

这似乎让我的应用非常头疼。我得到一个如下所示的异常:

CSV 似乎在位置“181”的记录“1470”字段“26”附近已损坏。当前原始数据:...

在那个“原始数据”中,确实索赔描述字段显示了带有引号的数据。

我想知道是否有人以前遇到过这个问题,并且解决了它? 显然,我可以要求客户更改他们最初发送给我的数据,但这是他们用来生成制表符分隔文件的自动化过程;我宁愿把它作为最后的手段。

我想我可以事先使用标准 TextReader 打开文件,转义任何引号,将内容写回新文件,然后将该文件输入 CSV 阅读器。值得一提的是,这些制表符分隔文件的平均文件大小约为 40MB。

非常感谢任何帮助!

干杯,肖恩

【问题讨论】:

    标签: c# csv quotes textreader


    【解决方案1】:

    查看codeproject文章关于引号的评论:

    http://www.codeproject.com/Messages/3382857/Re-Quotes-inside-of-the-Field.aspx

    您需要在构造函数中指定要使用除 " 之外的另一个字符作为引号。

    【讨论】:

    • +1 这是你需要做的。如果 " 在 CSV 的其他地方用作引号字符,则文件只是不一致并且没有干净的解决方案
    【解决方案2】:

    改用FileHelpers 库。它被广泛使用,可以处理带引号的字段或包含引号的字段。

    【讨论】:

    • @Oded:问题不在于如何处理引用字段。它询问包含引号字符的 unquoted 字段。
    • @Luke:嗯。我开始不同意你的观点,因为没有真正的 CSV“标准”。不过,我确实找到了一个 RFC,看起来你是对的。
    • @T.E.D. - 有 CSV 的 RFC,但没有制表符分隔的 RFC。
    • 好点。我想您可以说明它应该与 CSV RFC 相同,但使用制表符而不是逗号。不过,如果他们在 RFC 的某个地方说这样的话会更好。做到这一点并不难。
    【解决方案3】:

    我最近解决了一个类似的问题,尽管 CsvReader 在我的 TSV 文件的几行之外都可以正常工作,但最终解决我的问题是在 CsvReader 的构造函数中设置了一个 customDelimiter

    public static void ParseTSV(string filepath)
        {
            using (CsvReader csvReader = new CsvReader(new StreamReader(filepath), true, '\t')) {
            //if that didn't work, passing unlikely characters into the other params might help
            //using (CsvReader csvReader = new CsvReader(new StreamReader(filepath), true, '\t', '~', '`', '~', ValueTrimmingOptions.None)) {
                int fieldcount = csvReader.FieldCount;
    
                //Does not work, since it's read only property
                //csvReader.Delimiter = "\t";
    
                string[] headers = csvReader.GetFieldHeaders();
    
                while (csvReader.ReadNextRecord()) {
                    for (int i = 0; i < fieldcount; i++) {
                        string msg = String.Format("{0}\r{1};", headers[i],
                                                   csvReader[i]);
                        Console.Write(msg);
                    }
                    Console.WriteLine();
                }
            }
        }
    

    【讨论】:

      【解决方案4】:
      【解决方案5】:

      也许你可以用你的应用程序打开文件,用另一个字符替换每个引号,然后处理它。

      【讨论】:

        【解决方案6】:

        我做了一些搜索,有一个 CSV 文件的 RFC (RFC 4180),这确实明确禁止他们在做什么:

        每个字段可以用双引号括起来也可以不括起来(但是 某些程序(例如 Microsoft Excel)不使用双引号 完全)。如果字段没有用双引号括起来,那么 双引号不能出现在字段内。

        基本上,如果他们想这样做,他们需要将整个字段括在引号中,如下所示:

        ,""SUMISEI MARU NO 2" - sea of Japan",
        

        因此,如果您愿意,可以将这个问题抛给他们,并坚持让他们向您发送“正确”的 RFC 4180 CSV 文件。

        由于您可以访问该 CSV 阅读器的源文件,另一种选择是修改它以处理它们提供给您的带引号的字符串。

        这种情况正是让源代码访问您的工具集至关重要的原因。

        如果您想在将文件提供给您的工具之前对其文件进行预处理(破解),正确的方法是查找带有引号的字段,而不是紧接在分隔符之前或之后的字段,并将其包含在整个字段中在另一组引号中。

        【讨论】:

          【解决方案7】:

          是的 - 经过一个深夜的红牛和挠头后,我最终发现了问题,它是“Claim_Description”字段中的逗号。甚至没有考虑过这一点,因为我使用的是制表符分隔的文件,但是一旦我对文件中的所有逗号进行了查找和替换,它就工作得很好!

          下一步是在处理之前找出如何替换这些逗号。

          再次感谢您的所有建议。

          干杯,肖恩

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-06-02
            • 2021-09-28
            • 1970-01-01
            • 1970-01-01
            • 2019-11-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多