制表符分隔文件中的引号

Posted

技术标签:

【中文标题】制表符分隔文件中的引号【英文标题】: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。

非常感谢任何帮助!

干杯,肖恩

【问题讨论】:

【参考方案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\r1;", headers[i],
                                               csvReader[i]);
                    Console.Write(msg);
                
                Console.WriteLine();
            
        
    

【讨论】:

【参考方案4】:

使用 OleDbConnection http://social.msdn.microsoft.com/Forums/en/winformsdatacontrols/thread/98fce7d7-b02d-4027-ad2e-2df3a28bd439

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

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

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

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

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

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

【讨论】:

【参考方案7】:

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

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

再次感谢您的所有建议。

干杯,肖恩

【讨论】:

以上是关于制表符分隔文件中的引号的主要内容,如果未能解决你的问题,请参考以下文章

制表分隔文件到熊猫

第十七天python3 文件IO

对文本文件中制表符分隔列中的文本进行分类

数据文件的内容中,字段中间用制表符Tab键分隔。

制表符分隔文件的 OleDb 连接字符串

根据第一列组合几个制表符分隔文件的某些列