关闭。 此问题不符合堆栈溢出准则。它当前不接受答案。
想改善这个问题吗? 更新问题,使其成为Stack Overflow 的主题。
5年前关闭。
我正在查看一般基于MS堆栈(特别是.net)的分隔文件(例如CSV,制表符分隔等)解析选项。我要排除的唯一技术是SSIS,因为我已经知道它不能满足我的需求。
所以我的选择似乎是:
我必须满足两个条件。首先,给定以下文件,其中包含两个逻辑数据行(以及五个物理行):
101, Bob, "Keeps his house ""clean"". Needs to work on laundry." 102, Amy, "Brilliant. Driven. Diligent."
解析的结果必须产生两个逻辑“行”,每个行由三个字符串(或列)组成。第三行/列字符串必须保留换行符!换句话说,由于“未封闭”文本限定符,解析器必须识别行何时“继续”到下一个物理行。
第二个条件是,每个文件的定界符和文本限定符必须是可配置的。这是我必须能够解析的来自不同文件的两个字符串:
var first = @"""This"",""Is,A,Record"",""That """"Cannot"""", they say,"","""",,""be"",rightly,""parsed"",at all"; var second = @"~This~|~Is|A|Record~|~ThatCannot~|~be~|~parsed~|at all";
字符串“ first”的正确解析为:
“ _”只是表示捕获了一个空白-我不希望出现文字下划线。
可以对要解析的平面文件做出一个重要假设:每个文件中的列数是固定的。
现在开始深入探讨技术选择。
正则表达式
首先,许多响应者评论说正则表达式“不是实现目标的最佳方法”。但是,我确实找到了提供出色CSV正则表达式的评论者:
var regex = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"; var Regex.Split(first, regex).Dump();
应用于字符串“ first”的结果非常棒:
如果清理引号会很好,但是我可以轻松地将其作为后处理步骤来处理。否则,此方法可用于解析样本字符串“ first”和“ second”,前提是正则表达式已相应地针对代字号和管道符号进行了修改。优秀的!
但是真正的问题与多行标准有关。在将正则表达式应用于字符串之前,我必须从文件中读取完整的逻辑“行”。不幸的是,除非拥有正则表达式/状态机,否则我不知道要读取多少物理行才能完成逻辑行。
因此,这成为一个“鸡与蛋”的问题。我最好的选择是将整个文件作为一个大字符串读入内存,并让正则表达式整理出多行(我没有检查上面的正则表达式是否可以处理)。如果我有一个10 gig的文件,这可能有点不稳定。
转到下一个选项。
TextFieldParser
三行代码将使此选项的问题显而易见:
var reader = new Microsoft.VisualBasic.FileIO.TextFieldParser(stream); reader.Delimiters = new string[] { @"|" }; reader.HasFieldsEnclosedInQuotes = true;
Delimiters配置看起来不错。但是,“ HasFieldsEnclosedInQuotes”是“游戏结束”。我很震惊,定界符是可以任意配置的,但是相比之下,除了引号之外,我没有其他限定符选项。记住,我需要在文本限定符上具有可配置性。再说一次,除非有人知道TextFieldParser配置技巧,否则这一切就结束了。
OLEDB
一位同事告诉我,此选项有两个主要缺点。首先,它对大型文件(例如10 gig)的性能非常糟糕。其次,有人告诉我,它猜测输入数据的数据类型,而不是让您指定。不好。
帮帮我
因此,我想知道我错了的事实(如果有的话)以及我错过的其他选择。也许有人知道陪审团TextFieldParser使用任意定界符的方法。也许OLEDB已经解决了上述问题(或者也许从未解决过?)。
怎么说
您是否尝试搜索已经存在的.NET CSV解析器?这个声称可以比OLEDB更快地处理多行记录。