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

有帮助吗?

解决方案

  1. 文件的2GB巨大,您应该选择DB。
  2. 如果您真的想使用 Java I/O API, ,然后尝试一下: 使用Java有效地处理大型数据文件 和这个: 调整Java I/O性能

其他提示

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

最简单的方法是执行像GREP一样的事情:按行读取文件,分析线,检查您的过滤器标准,如果匹配,输出结果行,然后转到下一行,直到完成文件。这是非常有效的,因为您仅将当前线(或更大的缓冲区)同时加载。您的过程只需阅读一次整个文件。

我认为多个线程不会有太大帮助。这将使事情变得更加复杂,并且由于该过程似乎是i/o绑定的,因此尝试读取具有多个线程的同一文件可能不会改善吞吐量。

如果您发现自己需要经常执行此操作,并且每次都要慢慢进行文件,则需要构建某种索引。最简单的方法是首先将文件导入DB(可以是嵌入式DB或HSQL)。

除非您发现这种简单的方法对您需要的东西不起作用,否则我不会过度复杂化。本质上,您只需要:

  • 打开输入流到2GB文件,记住到缓冲区(例如,用BufferedInputStream包装)
  • 打开输出流到您要创建的过滤文件
  • 从输入流中读取第一个记录,查看任何属性以确定您是否需要“需要”;如果这样做,请将其写入输出文件
  • 重复其余记录

在我的一个带有极度适度硬件的测试系统上,盒子外面的FileInputStream在25秒内读取约500 MB,即可能不到2分钟来处理您的2GB文件,并且默认的缓冲区大小基本上一样好, (请参阅 BufferedInputStream定时 我为更多详细信息制作了)。我想,使用最先进的硬件,很有可能时间会减半。

无论您是需要付出很多努力来减少2/3分钟还是在等待运行的时候就去找Wee,这是一个决定,您必须根据自己的要求做出。我认为,除非您需要在同一数据集上进行许多不同的处理运行,否则数据库选项不会为您购买太多(并且还有其他解决方案不会自动含义数据库)。

我想你应该使用 内存映射 文件。这将帮助您将较大的文件映射到较小的内存中。此操作将像虚拟内存一样,就性能而言,映射的文件比流写入/读取的速度更快。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top