我一直在尝试处理一些带有非标准定界符(不是逗号/引号或制表符定界)的定界文本文件.分隔符是随机的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 IEnumerable<string[]> CreateEnumerable(StreamReader input)
{
string line;
while ((line = input.ReadLine()) != null)
{
yield return line.Split('þ');
}
}
这将为您提供简单的字符串数组,以流畅的方式表示行,甚至您也可以将Linq放入其中;)但是请记住IEnumerable是延迟加载的,因此在您迭代(或导致像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”的文件中打印出前两个字段.它将执行此操作而不会将整个文件加载到内存中.