我一直在尝试处理一些带有非标准分隔符(不是逗号/引号或制表符分隔符)的分隔文本文件.分隔符是随机ASCII字符,在分隔符之间不会显示.在搜索之后,我似乎只发现.NET中的解决方案不适合我的需求,人们为此编写的自定义库似乎在巨大的输入(4GB文件,其中包含一些字段值)时存在一些缺陷非常容易几百万字符).
虽然这看起来有点极端,但它实际上是电子文档发现(EDD)行业的标准,某些评论软件的字段值包含文档的全部内容.作为参考,我以前在使用csv模块的python中完成了这个,没有任何问题.
这是一个示例输入:
Field delimiter = quote character = þ þFieldName1þþFieldName2þþFieldName3þþFieldName4þ þValue1þþValue2þþValue3þþSomeVery,Very,Very,Large value(5MB or so)þ ...etc...
编辑:所以我继续从头开始创建一个分隔文件解析器.我有点厌倦使用这个解决方案,因为它可能容易出错.为这样的任务编写我自己的解析器也不会感觉"优雅"或正确.我也有一种感觉,无论如何我可能不必从头开始编写解析器.
使用File Helpers API.它是.NET和开源的.使用编译的IL代码在强类型对象上设置字段并支持流式传输,它具有极高的性能.
它支持各种文件类型和自定义分隔符; 我用它来读取大于4GB的文件.
如果由于某种原因不适合你,请尝试逐行阅读string.split:
public IEnumerableCreateEnumerable(StreamReader input) { string line; while ((line = input.ReadLine()) != null) { yield return line.Split('þ'); } }
这将给你简单的字符串数组,以流畅的方式表示你甚至可以Linq进入;但是请记住,IEnumerable是延迟加载的,所以在迭代之前不要关闭或改变StreamReader(或导致完全加载操作,如ToList/ToArray等 - 但鉴于你的文件大小,我假设你不会这样做!).
这是一个很好的样例用法:
using (StreamReader sr = new StreamReader("c:\\test.file")) { var qry = from l in CreateEnumerable(sr).Skip(1) where l[3].Contains("something") select new { Field1 = l[0], Field2 = l[1] }; foreach (var item in qry) { Console.WriteLine(item.Field1 + " , " + item.Field2); } } Console.ReadLine();
这将跳过标题行,然后从文件中打印出前两个字段,其中第4个字段包含字符串"something".它会在不将整个文件加载到内存的情况下执行此操作.