缓冲读取器和文件读取器之间的特定区别

2022-08-31 14:35:54

我想知道 和 之间的具体区别。BufferedReaderFileReader

我确实知道这比 更有效,但有人可以解释为什么(具体和详细)吗?谢谢。BufferedReaderFileReader


答案 1

首先,你应该了解Java中的“流”,因为Java中的所有“读者”都是基于这个概念构建的。

文件流

文件流由 Java 中的 FileInputStream 对象执行。

// it reads a byte at a time and stores into the 'byt' variable
int byt;
while((byt = fileInputStream.read()) != -1) {
    fileOutputStream.write(byt);
} 

此对象一次读取一个字节(8 位)并将其写入给定文件。

它的一个实际有用的应用是处理原始二进制/数据文件,例如图像或音频文件(使用AudioInputStream而不是FileInputStream进行音频文件)。另一方面,对于文本文件来说,这是非常不方便和较慢的,因为一次循环通过一个字节,然后做一些处理并将处理后的字节存储回去是繁琐和耗时的。

您还需要提供文本文件的字符集,即字符是拉丁文还是中文等。否则,程序将一次解码和编码8位,你会看到奇怪的字符打印在屏幕上或写在输出文件中(如果字符长度超过1字节,即非ASCII字符)。

文件读取

这只是一种花哨的说法,即“文件流”具有包容性字符集支持(即不需要像以前那样定义字符集)。

专门设计用于处理文本文件。如前所述,文件流最好处理原始二进制数据,但为了文本起见,它并不那么有效。

因此,Java-dudes添加了FileReader类,专门处理文本文件。它一次读取 2 个字节(或 4 个字节,具体取决于字符集)。与前面的 FileInputStream 相比,这是一个非常大的改进!!

所以流媒体操作是这样的,

int c;
while ( (c = fileReader.read()) != -1) { // some logic }

请注意,这两个类都使用整数变量来存储从输入文件中检索到的值(因此每个字符在提取时转换为整数,并在存储时返回到char)。

这里唯一的优点是,此类仅处理文本文件,因此您不必指定字符集和其他一些属性。它为大多数文本文件处理案例提供了开箱即用的解决方案。它还支持国际化和本地化。

但同样,它仍然非常慢(成像一次读取2个字节并循环通过它!

缓冲流

解决在一个或 2 个字节上连续循环的问题。Java-dudes增加了另一个壮观的功能。“在处理之前创建数据缓冲区。

当用户在YouTube上流式传输视频时,这个概念非常相似。视频在播放前经过缓冲,以提供完美的视频观看体验。(顺便说一句,浏览器会一直缓冲,直到整个视频提前缓冲。BufferedReader 类也使用相同的技术。

BufferedReader 对象将 FileReader 对象作为输入,该输入包含有关需要读取的文本文件的所有必要信息。(如文件路径和字符集。

BufferedReader br = new BufferedReader( new FileReader("example.txt") );

当向 BufferedReader 对象提供“read”指令时,它使用 FileReader 对象从文件中读取数据。当给出指令时,FileReader 对象一次读取 2(或 4)个字节,并将数据返回到 BufferedReader,读取器继续这样做,直到它命中 '\n' 或 '\r\n' (行符号的末尾)。缓冲一行后,读取器耐心等待,直到给出缓冲下一行的指令。

同时,BufferReader 对象创建一个特殊的内存位置(在 RAM 上),称为“缓冲区”,并存储从 FileReader 对象获取的所有数据。

// this variable points to the buffered line
String line;

// Keep buffering the lines and print it.
while ((line = br.readLine()) != null) {
    printWriter.println(line);
}

现在,不是一次读取2个字节,而是获取整行并将其存储在RAM中的某个地方,当您完成数据处理后,您可以将整行存储回硬盘。因此,它使该过程的运行速度比一次执行2个字节的速度快得多。

但是,为什么我们需要将FileReader对象传递给BufferReader?难道我们不能说“缓冲这个文件”,BufferReader会负责其余的吗?那不是很甜蜜吗?

好吧,BufferReader 类的创建方式只知道如何创建缓冲区和存储传入的数据。它与数据来自的对象无关。因此,同一对象可用于许多其他输入流,而不仅仅是文本文件。

因此,话虽如此,当您提供FileReader对象作为输入时,它会缓冲文件,就像如果您将 InputStreamReader 作为对象提供一样,它会缓冲终端/控制台输入数据,直到它命中换行符号。如

// Object that reads console inputs
InputStreamReader console = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(console);
System.out.println(br.readLine());

这样,您可以使用相同的 BufferReader 类读取(或缓冲)多个流,例如文本文件、控制台、打印机、网络数据等,您只需记住,

 bufferedReader.readLine();

以打印已缓冲的任何内容。


答案 2

简单来说:

FileReader 类是用于从文件中读取字符的通用工具。BufferedReader 类可以像 FileReader 一样环绕 Reader,以缓冲输入并提高效率。因此,您不会使用一个而不是另一个,而是通过将 FileReader 对象传递给 BufferedReader 构造函数来同时使用两者。

非常详细

FileReader 用于从磁盘文件输入字符数据。输入文件可以是普通的 ASCII,即每字符一个字节的文本文件。读取器流会自动将字符从磁盘文件格式转换为内部字符格式。输入文件中的字符可能来自 UTF 格式支持的其他字母表,在这种情况下,每个字符最多有三个字节。在这种情况下,文件中的字符也会转换为 char 格式。

enter image description here

与输出一样,最好使用缓冲区来提高效率。为此,请使用 BufferedReader。这与我们用于键盘输入的类相同。这些行应该看起来很熟悉:

BufferedReader stdin =
    new BufferedReader(new InputStreamReader( System.in ));

这些行创建一个 BufferedReader,但将其连接到键盘的输入流,而不是连接到文件。

资料来源:http://www.oopweb.com/Java/Documents/JavaNotes/Volume/chap84/ch84_3.html


推荐