当前位置: 首页 > 知识库问答 >
问题:

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

房星光
2023-03-14

我试图使用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;
        }

BufferedInputStream的速度快30倍以上。远不止这些。那么,这是为什么呢?有没有可能使这段代码更高效(不使用任何外部库)?

共有3个答案

卜季萌
2023-03-14

是因为磁盘访问的成本。让我们假设您将有一个大小为8kb的文件。8*1024次访问磁盘将需要读取该文件,而无需BufferedInputStream。

此时,BufferedStream进入场景并充当FileInputStream和要读取的文件之间的中间人。

在一个快照中,将获取字节块,默认值为8kb到内存,然后FileInputStream将从这个中间人读取字节。这将缩短操作时间。

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));
    }
秦雅逸
2023-03-14

围绕FileInputStream的BufferedInputStream将以大块形式(我认为默认情况下是512字节左右)从FileInputStream请求数据因此,如果一次读取1000个字符,FileInputStream只需进入磁盘两次。这会快得多!

卫才哲
2023-03-14

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;

这是对使用磁盘读取单个字节的操作系统的本机调用。这是一项繁重的行动。

使用BufferedInputStream,该方法委托给重载的read()方法,该方法读取8192字节数并缓冲它们,直到需要它们。它仍然只返回单个字节(但保留其他字节)。这样,BufferedInputStream对操作系统从文件中读取的本地调用就少了。

例如,您的文件是32768字节长。要使用FileInputStream获取内存中的所有字节,需要对操作系统进行32768本机调用。使用BufferedInputStream,您将只需要4,而不管您将执行read()调用的数量(仍然是32768)。

至于如何使它更快,您可能需要考虑java 7的NiO FieleChans类,但我没有证据支持这一点。

注意:如果直接使用FileInputStreamread(byte[], int, int)方法,则使用byte[

 类似资料:
  • 问题内容: 我试图使用FileInputStream将文件读入数组,而一个〜800KB的文件花了大约3秒钟才能读入内存。然后,我尝试了相同的代码,只是将FileInputStream包装到BufferedInputStream中,这花费了大约76毫秒。为什么即使我仍在逐字节读取文件,使用BufferedInputStream逐字节读取文件的速度还是这么快?这是代码(其余代码完全无关)。请注意,这是

  • bufferedinputstream(BIS)比FileInputStream(FIS)快的原因请参见“为什么使用bufferedinputstream逐字节读取文件比使用FileInputStream快?”?是吗 使用BufferedInputStream,该方法委托给重载read()方法,该方法读取8192个字节,并在FIS读取单个字节时缓冲它们,直到需要它们 据我所知,磁盘是一个“块设备”

  • 问题内容: 我有一个要在Java中读取的2 gb文件(实际上是四个2gb文件)。因此,Java 7中有一个新功能,可以让我一次读取所有字节。 这是一个愚蠢的程序,它将读取文件中预先输入一个字节的文件,然后连续读取该文件,并将读取的内容附加到同一文件中。现在显然,RAM不够大,无法一次读取2gb文件,更不用说其中的四个了,所以我想知道是否有任何快速方法,而无需使用外部库(除非这是唯一方法)来读取四个

  • 问题内容: 如何使用fseek逐行读取文件? 代码可能会有所帮助。必须是跨平台和纯PHP。 提前谢谢了 问题答案: 问题是使用fseek进行询问,因此只能假定性能是一个问题,而file()不是解决方案。这是使用fseek的一种简单方法: 我的file.txt 和代码: 输出: 您不必像我一样附加到$ lines数组,如果这是脚本的目的,则可以立即打印输出。如果要限制行数,也很容易引入计数器。

  • 本文向大家介绍Java使用FileInputStream / FileOutputStream读/写文件,包括了Java使用FileInputStream / FileOutputStream读/写文件的使用技巧和注意事项,需要的朋友参考一下 示例 写入文件test.txt: 从文件test.txt中读取: 请注意,自Java 1.7起引入了try-with-resources语句,这使得读/写操

  • 问题内容: 我在S3中有一个csv文件,我正在尝试读取标题行以获取大小(这些文件是由我们的用户创建的,因此它们几乎可以是任何大小)。有没有办法使用boto做到这一点?我以为也许我们可以使用python BufferedReader,但是我不知道如何从S3键打开流。任何建议都很好。谢谢! 问题答案: 看来boto具有可以执行此操作的功能。这是一些对我有用的代码: 调用会从对象返回下一个n个字节。 当