java - InputStream、InputStreamReader 和 BufferedReader 如何在 Java 中协同工作?

标签 java android inputstream bufferedreader inputstreamreader

我正在学习 Android 开发(我是一般编程的初学者)并学习 HTTP 网络,并在类(class)中看到了这段代码:

private String readFromStream(InputStream inputStream) throws IOException {
  StringBuilder output = new StringBuilder();
  if (inputStream != null) {
    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
    BufferedReader reader = new BufferedReader(inputStreamReader);
    String line = reader.readLine();
    while (line != null) {
      output.append(line);
      line = reader.readLine();
    }
  }
  return output.toString();
}

我不明白 InputStream、InputStreamReader 和 BufferedReader 到底是做什么的。它们都有一个 read() 方法,在 BufferedReader 的情况下还有 readLine()。为什么我不能只使用 InputStream 或只添加 InputStreamReader?为什么我需要添加 BufferedReader?我知道这与效率有关,但我不明白这是怎么回事。

我一直在研究 documentation for the BufferedReader试图解释这一点,但我仍然不明白谁在做什么:

In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,

BufferedReader in = new BufferedReader(new FileReader("foo.in")); will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

所以,我知道 InputStream 只能读取一个字节,InputStreamReader 只能读取一个字符,而 BufferedReader 只能读取整行,而且它还可以提高效率,这是我不明白的。我想更好地了解谁在做什么,以便理解为什么我需要这三者以及没有其中之一会有什么不同。

我在这里和网络上的其他地方进行了很多研究,似乎没有找到任何我能理解的解释,几乎所有教程都只是重复文档信息。这里有一些相关的问题可能会开始解释这个但不要更深入地解决我的困惑:Q1 , Q2 , Q3 , Q4 .我想这可能与最后一个问题对系统调用和返回的解释有关。但我想了解这一切的含义。

会不会是 BufferedReader 的 readLine() 调用了 InputStreamReader 的 read() 方法,而 InputStreamReader 的 read() 方法又调用了 InputStream 的 read() 方法?并且 InputStream 返回转换为 int 的字节,一次返回一个字节,InputStreamReader 读取足够多的字节来生成单个字符并将其转换为 int 并一次返回一个字符,BufferedReader 读取足够多的这些字符表示为整数来组成整行?并将整行作为字符串返回,只返回一次而不是多次?我不知道,我只是想知道事情是如何运作的。

非常感谢!

最佳答案

Streams in Java concepts and usage链接,给出一个很好的解释。

This

Streams、Readers、Writers、BufferedReader、BufferedWriter – 这些是您将在 Java 中处理的术语。 Java 中提供了一些类来处理输入和输出。真正值得了解它们之间的关系以及它们的使用方式。这篇文章将详细探讨 Java 中的 Streams 和其他相关类。那么让我们开始吧:

让我们在高层次上定义每一个,然后深入挖掘。


用于处理字节级数据

读者/作家
用来处理人物等级。它还支持各种字符编码。

BufferedReader/BufferedWriter
以提高性能。要读取的数据将缓存到内存中,以便快速访问。

虽然这些用于获取输入,但也只有相应的类用于输出。例如,如果有一个用于读取字节流的 InputStream,而 OutputStream 将有助于写入字节流。

输入流
java提供了多种类型的InputStreams。每个都连接到不同的数据源,例如字节数组、文件等。

例如,FileInputStream 连接到文件数据源,可用于从文件中读取字节。而 ByteArrayInputStream 可用于将字节数组视为输入流。

输出流
这有助于将字节写入数据源。几乎每个 InputStream 都有对应的 OutputStream,只要它有意义。


更新

什么是缓冲流?

这里我引用自Buffered Streams , Java 文档(附技术说明):

Buffered Streams

Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.

To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

有时候,我在阅读技术文档时会头皮发麻。所以,这里引用https://yfain.github.io/Java4Kids/比较人性化的解释 :

In general, disk access is much slower than the processing performed in memory; that’s why it’s not a good idea to access the disk a thousand times to read a file of 1,000 bytes. To minimize the number of times the disk is accessed, Java provides buffers, which serve as reservoirs of data.

enter image description here

In reading File with FileInputStream then BufferedInputStream, the class BufferedInputStream works as a middleman between FileInputStream and the file itself. It reads a big chunk of bytes from a file into memory (a buffer) in one shot, and the FileInputStream object then reads single bytes from there, which are fast memory-to-memory operations. BufferedOutputStream works similarly with the class FileOutputStream.

The main idea here is to minimize disk access. Buffered streams are not changing the type of the original streams — they just make reading more efficient. A program performs stream chaining (or stream piping) to connect streams, just as pipes are connected in plumbing.

关于java - InputStream、InputStreamReader 和 BufferedReader 如何在 Java 中协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43147069/

相关文章:

java - 如何在maven应用程序中使用heroku环境变量绑定(bind)http服务器

java - 更新语句在 SQLite 浏览器中工作,而不是在 java 中使用完全相同的语法

java - 如何从 java.lang.String 获取 java.io.InputStream?

java - 复制 InputStream,如果大小超过限制则中止操作

java - Lombok 构建器覆盖默认构造函数

java - 从类路径访问资源文件

android - 如何捕捉 map 调整大小的结束

android - 是否可以以编程方式运行 InstrumentationTestRunner?

android - 从 Android 应用程序登录网页

java - 在写入时从 ByteArrayOutputStream 中读取