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

我试图通过使用FileInputStream将文件读入数组,而一个〜800KB的文件花费了大约3秒的时间读入内存。 然后我尝试了相同的代码,除了FileInputStream包装到一个BufferedInputStream,大约需要76毫秒。 为什么用BufferedInputStream读取一个字节的文件逐字节地完成,尽pipe我还在逐字节读取它? 这里的代码(其余的代码是完全不相关的)。 请注意,这是“快速”的代码。 如果你想要“慢”代码,你可以删除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; } 

BufferedInputStream速度超过30倍。 远不止这些。 那么,为什么是这样,是否有可能使这个代码更有效率(不使用任何外部库)?

FileInputStreamread()方法读取一个字节。 从源代码:

 /** * 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; 

这是使用磁盘读取单个字节的操作系统的本地调用。 这是一个沉重的操作。

使用BufferedInputStream ,该方法将委派一个重载的read()方法,该方法读取8192个字节的数量并caching它们,直到需要为止。 它仍然只返回单个字节(但保留其他的)。 通过这种方式, BufferedInputStream对操作系统进行的本地调用可以从文件中读取。

例如,您的文件长度为32768个字节。 要使用FileInputStream获取内存中的所有字节,您需要32768本地调用操作系统。 使用BufferedInputStream ,无论read()调用的数量是多less(仍然是32768 ),只需要4

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

一个包裹在FileInputStream中的BufferedInputStream将以大块的方式从FileInputStream请求数据(默认512字节左右)。因此,如果每次读取1000个字符,FileInputStream将只需要两次。 这将会快得多!

的FileReader

FileReader是用于读取字符stream。

的BufferedReader

从字符inputstream中读取文本,缓冲字符以提供对字符,数组和行的有效读取。

根据文档FileReader对每一个读操作提出请求,这是昂贵的。
BufferedReader在缓冲区填充时发出请求。

根据文件

通常,由Reader构成的每个读取请求都会导致相应的读取请求由底层字符或字节stream组成。 因此,build议将BufferedReader包装在read()操作可能代价高昂的任何Reader中,例如FileReaders和InputStreamReaders。

阅读这个http://oopweb.com/Java/Documents/JavaNotes/Volume/chap84/ch84_3.html

这是因为磁盘访问的成本。 让我们假设你将有一个大小为8kb的文件。 8 * 1024次访问磁盘将需要读取此文件没有BufferedInputStream。

在这一点上,BufferedStream来到现场,并充当FileInputStream和要读取的文件之间的中间人。

在一个镜头中,将获得大块的字节默认是8kb的内存,然后FileInputStream将从这个中间人读取字节。 这将减less操作的时间。

 private void exercise1WithBufferedStream() { long start= System.currentTimeMillis(); try (FileInputStream myFile = new FileInputStream("anyFile.txt")) { BufferedInputStream bufferedInputStream = new BufferedInputStream(myFile); boolean eof = false; while (!eof) { int inByteValue = bufferedInputStream.read(); if (inByteValue == -1) eof = true; } } catch (IOException e) { System.out.println("Could not read the stream..."); e.printStackTrace(); } System.out.println("time passed with buffered:" + (System.currentTimeMillis()-start)); } private void exercise1() { long start= System.currentTimeMillis(); try (FileInputStream myFile = new FileInputStream("anyFile.txt")) { boolean eof = false; while (!eof) { int inByteValue = myFile.read(); if (inByteValue == -1) eof = true; } } catch (IOException e) { System.out.println("Could not read the stream..."); e.printStackTrace(); } System.out.println("time passed without buffered:" + (System.currentTimeMillis()-start)); }