2010-08-20 67 views
1

我有一个大小为2GB的文件,其中有学生记录。我需要根据每条记录中的某些属性找到学生,并创建一个包含结果的新文件。过滤学生的顺序应与原始文件中的顺序相同。使用Java IO API和线程执行此操作的最快方法是什么,而没有内存问题? JVM的maxheap大小设置为512MB。java中的文件处理

+2

考虑将信息存储在数据库而不是2GB文件中。为学生做。 – polygenelubricants 2010-08-20 01:14:39

+0

数据库不适合我。我会用纯文本文件获取数据,我必须处理它。 – 2010-08-20 01:19:17

+0

无法将X磅的任何东西放入X/N包中,其中N> 1。您将永远不会将该文件的全部内容一次性压缩到内存中。 – duffymo 2010-08-20 01:24:49

回答

6

什么样的文件?基于文本的,如CSV?

最简单的方法是做类似grep的事情:逐行读取文件,解析行,检查过滤条件,如果匹配,输出结果行,然后转到下一行,直到文件已经完成了。这非常有效,因为您只有当前行(或缓冲区稍大)加载的同时。你的过程需要通读整个文件一次。

我不认为多线程会有很大的帮助。这会让事情变得更加复杂,并且由于无论如何这个过程似乎都是I/O约束,试图用多个线程读取同一个文件可能不会提高吞吐量。

如果你发现你需要经常这样做,每次浏览文件太慢,你需要建立某种索引。最简单的方法是先将文件导入数据库(可以是SQLite或HSQL等嵌入式数据库)。

+0

哦,男孩,我打字完全一样的答案。事实上,所有这些都归结为只是一行一行地完成这项工作,而不是将整个事情存储在Java的内存中。 – BalusC 2010-08-20 01:34:17

5

我不会过度复杂,直到你发现无聊简单的方式不适合你的需要。从本质上讲,你只需要:

  • 打开的输入流为2GB的文件,记住缓冲液(如用的BufferedInputStream包装)
  • 打开的输出流过滤的文件,你要创建
  • 读第一条记录从输入流中,查看任何属性来决定是否“需要”它;如果这样做,将其写入到输出文件
  • 重复的剩余记录

我与极为有限的硬件测试系统之一,围绕一个FileInputStream的BufferedInputStream开箱即在25秒内,即阅读约500 MB大概在2分钟内处理你的2GB文件,并且默认的缓冲区大小基本上和它一样好(参见我所做的BufferedInputStream timings了解更多细节)。我想用最先进的硬件设备很可能时间会减半。

无论您需要花费很多精力来减少2/3分钟,或者只是在等待它运行的时间里等待一小段时间,您需要根据您的要求做出决定。我认为数据库选项不会给你多少钱,除非你需要在同一组数据上做很多不同的处理运行(还有其他解决方案不会自动表示数据库)。

+0

+1,尤指因为“在你等待的时候过一小会儿” – 2010-08-20 04:16:42

0

我认为你应该使用memory mapped files.This将帮助你映射较大的文件到一个 较小的内存。这将像虚拟内存一样行事,就性能而言,映射文件比流写/读。