1

我需要我的应用程序能够读取大型(非常大,100GB+)文本文件,并可能在不同时间处理这些文件中的内容。例如,它可能会运行一个小时并完成几 GB 的处理,然后我将其关闭并在几天后返回以恢复处理同一个文件。

为此,我需要将文件读入内存友好的块;每个块/页/块/等将被读取,一次一个,处理,然后下一个块被读入内存。

我需要程序能够标记它在输入文件中的位置,所以如果它关闭,或者如果我需要“重播”正在处理的最后一个块,我可以直接跳转到文件中我所在的位置并继续处理。具体来说,我需要能够做以下事情:

  • 当处理开始时,扫描文件以查找“MARKER”(一些标记,指示我们上次停止处理的位置)
  • 如果 MARKER 存在,跳转到它并从该点开始处理
  • 否则,如果 MARKER 不存在,则在第一个块之后放置一个 MARKER(现在,假设“块”只是一个文本行,就像BufferedReader#readLine()读入的那样)并开始处理第一个块/线
  • 对于处理的每个块/行,将标记移动到下一个块之后(因此,将标记进一步向下推进文件)
  • 如果我们到达在当前 MARKER 之后没有更多块/行的点,我们已经完成了文件的处理

我尝试自己编写代码,并注意到BufferedReader上面有一些有趣的方法,听起来它们非常适合这个目的:mark()、、reset()等等。但是它们上面的 Javadocs 有点含糊,我不确定这些“文件标记”方法将完成我需要做的所有事情。我也完全对内置此功能的 3rd 方 JAR/lib 持开放态度,但 Google 没有提出任何建议。

这里有什么想法吗?

4

3 回答 3

1

忘记标记。您不能在不重写整个文件的情况下“插入”文本。

使用 aRandomAccessFile并存储您正在阅读的当前位置。当您需要再次打开文件时,只需使用seek查找位置即可。

于 2013-10-16T12:19:27.277 回答
0

读者的“标记”不是持久的;它仅构成 Reader 本身状态的一部分。

我建议您不要将状态信息存储在文本文件本身中;相反,有一个文件旁边存储最近处理的块的字节偏移量。这将消除涉及覆盖原始文本文件中的数据的明显问题。

于 2013-10-16T12:19:39.670 回答
0

在应用程序的不同运行之后,缓冲读取器的标记不会持久化。我不会更改那个巨大文件的内容来标记位置,因为这可能会导致严重的 IO 和/或文件系统碎片,具体取决于您的操作系统。

我会使用属性文件在外部存储程序的配置。看看文档,API 很简单:

http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html

于 2013-10-16T12:20:15.093 回答