【问题标题】:Fastest way of reading relatively huge byte-files in Java在 Java 中读取相对较大的字节文件的最快方法
【发布时间】:2026-01-25 07:00:01
【问题描述】:

使用 Java 的 I/O 方法读取相对较大的文件最快的方法是什么?我当前的解决方案使用BufferedInputStream 保存到分配有1024 个字节的字节数组。然后将每个缓冲区保存在ArrayList 中以供以后使用。整个过程通过单独的线程(callable-interface)调用。

虽然不是很快。

    ArrayList<byte[]> outputArr = new ArrayList<byte[]>();      
    try {
        BufferedInputStream reader = new BufferedInputStream(new FileInputStream (dir+filename));

        byte[] buffer = new byte[LIMIT]; // == 1024 
            int i = 0;
            while (reader.available() != 0) {
                reader.read(buffer);
                i++;
                if (i <= LIMIT){
                    outputArr.add(buffer);
                    i = 0;
                    buffer = null;
                    buffer = new byte[LIMIT];
                }
                else continue;              
            }

         System.out.println("FileReader-Elements: "+outputArr.size()+" w. "+buffer.length+" byte each.");   

【问题讨论】:

  • 查看 Apache Commons 库以获取更多选项。要确定速度,请查看 O'Reilly 的 Java Performance Tuning 一书。
  • 目前您忽略了 read() 调用返回的值。 不要那样做。

标签: java performance file-io


【解决方案1】:

我会使用一个足够快的内存映射文件,可以在同一个线程中完成。

final FileChannel channel = new FileInputStream(fileName).getChannel();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

// when finished
channel.close();

这假设文件小于 2 GB,需要 10 毫秒或更短时间。

【讨论】:

  • 该死的!这东西怎么这么快?无论如何,谢谢,完美运行。 (编辑:它从内存中获取文件,java 文档刚刚告诉我。聪明)
  • 如果您需要访问超过 2 GB 的空间,则需要使用多个映射。
  • @PeterLawrey 在同一行上是否有将大输入流转换为字节数组的有效方法?例如,从 ContainerRequestContext 读取输入流?
【解决方案2】:

不要使用available():它不可靠。并且不要忽略read() 方法的结果:它会告诉您实际读取了多少字节。如果您想读取内存中的所有内容,请使用 ByteArrayOutputStream 而不是使用List&lt;byte[]&gt;

ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read;
while ((read = reader.read(buffer)) >= 0) {
    baos.write(buffer, 0, read);
}
byte[] everything = baos.toByteArray();

我认为 1024 作为缓冲区大小有点小。我会使用更大的缓冲区(比如 16 KB 或 32KB)

请注意,Apache commons IO 和 Guava 具有为您执行此操作的实用方法,并且已经过优化。

【讨论】:

    【解决方案3】:

    看看 Java NIO(非阻塞输入/输出)API。此外,this question 可能会很有用。

    我在 IO 方面没有太多经验,但我听说NIO 是处理大量数据的更有效方式。

    【讨论】: