为什么使用BufferedInputStream比使用FileInputStream更快地逐字节读取文件?

Zim*_*Zim 60 java file-io inputstream fileinputstream

我试图通过使用FileInputStream将文件读入数组,并且~800KB文件花了大约3秒来读入内存.然后我尝试了相同的代码,除了将FileInputStream包装到BufferedInputStream中,它花了大约76毫秒.为什么使用BufferedInputStream以字节逐字节读取文件,即使我仍在逐字节读取它?这是代码(代码的其余部分完全不相关).请注意,这是"快速"代码.如果你想要"慢"代码,你可以删除BufferedInputStream:

InputStream is = null;

    try {
        is = new BufferedInputStream(new FileInputStream(file));

        int[] fileArr = new int[(int) file.length()];

        for (int i = 0, temp = 0; (temp = is.read()) != -1; i++) {
            fileArr[i] = temp;
        }
Run Code Online (Sandbox Code Playgroud)

BufferedInputStream的速度提高了30多倍.远不止于此.那么,为什么会这样,并且可以使这个代码更有效(不使用任何外部库)?

Sot*_*lis 111

FileInputStream,该方法read()读取单个字节.从源代码:

/**
 * Reads a byte of data from this input stream. This method blocks
 * if no input is yet available.
 *
 * @return     the next byte of data, or <code>-1</code> if the end of the
 *             file is reached.
 * @exception  IOException  if an I/O error occurs.
 */
public native int read() throws IOException;
Run Code Online (Sandbox Code Playgroud)

这是对OS的本机调用,它使用磁盘读取单个字节.这是一个繁重的操作.

使用a BufferedInputStream,该方法委托给一个重载read()方法,该方法读取8192字节数并缓冲它们直到需要它们为止.它仍然只返回单个字节(但保留其他字节).这样,BufferedInputStream可以减少对OS的本机调用以从文件中读取.

例如,您的文件长度为32768字节.要使用a获取内存中的所有字节FileInputStream,您需要32768对操作系统进行本机调用.使用a BufferedInputStream,您只需要4,无论read()您将进行多少次通话(仍然32768).

至于如何使它更快,你可能想要考虑Java 7的NIO FileChannel类,但我没有证据支持这一点.

  • @ user1007059不客气.请注意,如果您直接使用`FileInputStream`的`read(byte [],int,int)`方法,使用`byte [> 8192]`,您将不需要包含它的`BufferedInputStream`. (12认同)