代码之家  ›  专栏  ›  技术社区  ›  Srini Kandula

Java中的文件处理

  •  1
  • Srini Kandula  · 技术社区  · 16 年前

    我有一个2GB大小的文件,里面有学生记录。我需要根据每个记录中的某些属性查找学生,并创建一个包含结果的新文件。筛选出的学生的顺序应与原始文件中的顺序相同。用Java IO API和线程来做这件事有效率和最快的方法,而没有内存问题?JVM的最大堆大小设置为512MB。

    4 回复  |  直到 16 年前
        1
  •  2
  •   Community Mohan Dere    11 年前
    1. 2GB对于一个文件来说是巨大的,您应该使用一个DB。
    2. 如果你真的想用 Java I/O API ,然后尝试: Handling large data files efficiently with Java 而这: Tuning Java I/O Performance
        2
  •  6
  •   Thilo    16 年前

    什么文件?基于文本,比如csv?

    最简单的方法是像grep那样做:逐行读取文件,解析该行,检查筛选条件,如果匹配,输出结果行,然后转到下一行,直到文件完成。这是非常节省内存的方法,因为您只需要同时加载当前行(或稍大一点的缓冲区)。您的过程只需要读取整个文件一次。

    我认为多线程不会有多大帮助。这将使事情变得更加复杂,而且由于进程似乎是I/O绑定的,因此尝试用多个线程读取同一个文件可能不会提高吞吐量。

    如果您发现需要经常这样做,并且每次浏览文件的速度太慢,那么您需要构建某种索引。最简单的方法是先将文件导入数据库(可以是像sqlite或hsql这样的嵌入式数据库)。

        3
  •  5
  •   Neil Coffey    16 年前

    除非你发现这种简单的方法不能满足你的需要,否则我不会对此做过多的解释。基本上你只需要:

    • 将输入流打开到2GB文件,记住缓冲(例如,使用BufferedInputStream包装)
    • 打开输出流到要创建的筛选文件
    • 从输入流读取第一条记录,查看任何属性以决定是否需要它;如果需要,将其写入输出文件。
    • 对其余记录重复

    在我的一个具有非常普通硬件的测试系统上,BufferedInputStream在25秒内读取大约500 MB,也就是说,处理2GB文件可能不到2分钟,默认缓冲区大小基本上与实际大小相同(请参见 BufferedInputStream timings 我做了更多的细节)。我想,有了最先进的硬件,时间可能会减少一半。

    无论你是需要花费大量的精力来减少2/3分钟,还是在等待它运行的时候花一点时间,这都是你必须根据自己的需求做出的决定。我认为数据库选项不会给您带来太多好处,除非您需要在同一组数据上执行大量不同的处理运行(而且还有其他解决方案不会自动意味着数据库)。

        4
  •  0
  •   Emil    16 年前

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