使用.NET的CSV解析选项

Bre*_*ias 13 .net c# parsing

我正在查看我的分隔文件(例如CSV,tab分离等)解析选项,一般基于MS堆栈,特别是.net.我排除的唯一技术是SSIS,因为我已经知道它不能满足我的需求.

所以我的选择似乎是:

  1. Regex.Split
  2. TextFieldParser
  3. OLEDB CSV解析器

我有两个必须符合的标准.首先,给定以下文件,其中包含两个逻辑数据行(以及共五个物理行):

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";
Run Code Online (Sandbox Code Playgroud)

正确解析字符串"first"将是:

  • 这个
  • 是,A,记录
  • 他们说,"不能"
  • _
  • _
  • 正当地
  • 解析的
  • 一点都不

'_'仅表示捕获了空白 - 我不希望出现文字下划线.

可以对要解析的平面文件做出一个重要的假设:每个文件将有固定数量的列.

现在深入了解技术方案.

正则表达式

首先,许多响应者评论说正则表达式"不是实现目标的最佳方式".但是,我确实找到了一位提供优秀CSV正则表达式评论者:

var regex = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
var Regex.Split(first, regex).Dump();
Run Code Online (Sandbox Code Playgroud)

应用于字符串"first"的结果非常精彩:

  • "这个"
  • "是,A,记录"
  • 他们说,"那个""不能"","
  • ""
  • _
  • "是"
  • 正当地
  • "解析"
  • 一点都不

如果清除报价会很好,但我可以轻松地将其作为后处理步骤来处理.否则,此方法可用于解析样本字符串"first"和"second",前提是相应地修改了正则表达式和管道符号.优秀!

但真正的问题与多线标准有关.在将正则表达式应用于字符串之前,我必须从文件中读取完整的逻辑"行".不幸的是,我不知道要读取多少物理行来完成逻辑行,除非我有一个正则表达式/状态机.

所以这成了"鸡与鸡蛋"的问题.我最好的选择是将整个文件作为一个巨大的字符串读入内存,让正则表达式排序多行(我没有检查上面的正则表达式是否可以处理).如果我有一个10 gig文件,这可能有点不稳定.

到下一个选项.

TextFieldParser

三行代码将使此选项的问题变得明显:

var reader = new Microsoft.VisualBasic.FileIO.TextFieldParser(stream);
reader.Delimiters = new string[] { @"|" };
reader.HasFieldsEnclosedInQuotes = true;
Run Code Online (Sandbox Code Playgroud)

Delimiters配置看起来不错.但是,"HasFieldsEnclosedInQuotes"是"游戏结束".令我震惊的是,分隔符是可任意配置的,但相比之下我除了引用之外没有其他限定符选项.请记住,我需要对文本限定符进行配置.所以,除非有人知道TextFieldParser配置技巧,否则这就是游戏结束.

OLEDB

一位同事告诉我这个选项有两个主要的缺点.首先,它对于大型(例如10Gig)文件具有可怕的性能.其次,我被告知,它会猜测输入数据的数据类型,而不是让你指定.不好.

救命

所以我想知道我弄错的事实(如果有的话),以及我错过的其他选项.也许有人知道陪审团使用任意分隔符的方法.也许OLEDB已经解决了所述的问题(或者从未有过它们?).

你说什么?

Dou*_*rch 6

您是否尝试搜索已存在的.NET CSV解析器这个声称处理多行记录比OLEDB快得多.