解析大型文本文件,实时修改

6
我需要实时解析一个大型CSV文件,同时该文件正在被不同的进程修改(追加)。这里的“大型”指的是目前约20GB,并且在缓慢增长。该应用程序只需要检测并报告数据流中的某些异常情况,对于这些情况,它只需要存储小的状态信息(O(1)空间)。
我考虑每隔几秒钟轮询文件的属性(大小),打开只读流,在先前的位置上寻找,然后继续解析我停止的地方。但由于这是一个文本(CSV)文件,显然需要在继续时跟踪换行符,以确保始终解析完整行。
如果我没有弄错,这应该不难实现,但我想知道是否有常见的方法/库已经解决了其中的一些问题?
注意:我不需要CSV解析器。我需要关于一个简化从正在实时修改的文件中读取行的库的信息。

可以停止 CSV 文件的处理吗?如果可以,我建议您将其转移到 RDBMS 上。 - Oybek
@Oybek:你能再具体解释一下吗?正在向文件中追加的进程一直在运行,我需要不断地逐行分析数据(并带有几秒钟的延迟)。 - vgru
不,我没有对生产者进行控制。这是一个收集数据并不断写入一个非常大的文件的应用程序,直到您的磁盘空间用尽。 - vgru
这是一个ASCII/ANSII文件还是UTF-8文件? - H H
@Henk:应该是7位ASCII码,只有一些Guid和数字。 - vgru
显示剩余3条评论
3个回答

2

我没有测试过,但是我认为你可以使用FileSystemWatcher来检测其他进程何时修改了你的文件。在Changed事件中,你将能够寻找之前保存的位置,并读取额外的内容。


1

这里有一个小问题:

  • 阅读和解析CSV需要一个TextReader
  • 使用TextReaders定位(很好)无法工作。

第一个想法:保持开放状态。如果生产者和分析器都以非独占模式运行,就应该能够ReadLine-until-null,暂停,ReadLine-until-null等。


应该是7位ASCII码,只包含一些Guid和数字。

这使得跟踪文件位置成为可能(pos += line.Length+2)。确保使用 Encoding.ASCII 打开它。然后可以将其重新打开为普通的二进制流,Seek到最后位置,然后才将StreamReader附加到该流上。


0
为什么不在每次开始解析时分离出一个单独的进程/线程 - 这样,您就可以将并发(即时)部分从数据源移动到数据汇中 - 现在您只需要想办法收集所有线程的结果...
但是这意味着您需要为每个线程重新读取整个文件...
您可以在两个版本上运行差异程序,并从那里继续,具体取决于csv数据源的格式:它是否修改已写入的记录?还是只附加新记录?如果是后者,则可以将新内容(最后位置到当前eof)拆分成一个新文件,并在后台线程中悠闲地处理:
- 轮询线程记住上次文件大小 - 当文件变大时:从上次位置到结尾查找,保存到临时文件 - 后台线程按创建/修改顺序处理任何仍留在临时文件中的文件

1
每秒追加的数据大小相对于整个文件大小来说比较小,这就是为什么我想避免每次读取它(在一周的测量后可能会轻松达到50GB)。由于数据只是追加的,而文件非常大,因此差异不实用。我也不理解线程的部分:由于这是磁盘操作,读取不会从多个线程中受益,只会更慢,在我将部分文件写入磁盘然后再次打开它的步骤似乎也是多余的(如果我正在复制它,我可能会解析它)。 - vgru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接