11

1) 缓冲流如何在后台工作,它们与普通流有何不同,使用它们有什么优势?

2)DataInputStream也是基于字节的。但它有方法readLine()。这里有什么意义?

4

5 回答 5

8

从 BufferedInputStream javadoc:

BufferedInputStream 向另一个输入流添加了功能,即缓冲输入并支持标记和重置方法的能力。创建 BufferedInputStream 时,会创建一个内部缓冲区数组。当流中的字节被读取或跳过时,内部缓冲区会根据需要从包含的输入流中重新填充,一次很多字节。标记操作会记住输入流中的一个点,并且重置操作会导致在从包含的输入流中获取新字节之前重新读取自最近一次标记操作以来读取的所有字节。

在内部使用缓冲区数组,而不是从底层输入流中单独读取字节,而是读取足够的字节来填充缓冲区。这通常会导致更快的性能,因为底层输入流需要更少的读取。

BufferedOutputStream 则相反。

mark() 和 reset() 可以按如下方式使用:

1 BufferedInputStream bis = new BufferedInputStream(is);
2 byte[] b = new byte[4];
3 bis.read(b); // read 4 bytes into b
4 bis.mark(10); // mark the stream at the current position - we can read 10 bytes before the mark point becomes invalid
5 bis.read(b); // read another 4 bytes into b
6 bis.reset(); // resets the position in the stream back to when mark was called
7 bis.read(b); // re-read the same 4 bytes as line 5 into b

要解释标记/重置更多...

BufferInputStream 在内部记住缓冲区中的当前位置。当您读取字节时,位置将增加。调用 mark(10) 将保存当前位置。随后对 read 的调用将继续增加当前位置,但对 reset 的调用会将当前位置设置回调用 mark 时的值。

mark 的参数指定在标记位置失效之前调用 mark 之后可以读取的字节数。一旦标记位置失效,您就不能再调用reset返回它。

例如,如果在上面的第 4 行中使用了 mark(2),则在第 6 行调用 reset() 时将引发 IOException,因为我们读取了超过 2 个字节,因此标记位置将无效。

于 2009-11-12T10:50:23.370 回答
8

缓冲的 Readers/Writers/InputStreams/OutputStreams 以大块的形式读取和写入 OS 以进行优化。在写入器和输出流的情况下,数据被缓冲在内存中,直到收集到足够的数据来写出一个大块。在读取器和输入流的情况下,从磁盘/网络/...读取一个大块到缓冲区中,所有读取都从该缓冲区完成,直到缓冲区为空,然后读入一个新块。

DataInputStream 确实是基于字节的。不推荐使用 readLine 方法。在内部,它从磁盘/网络/...逐字节读取字节,直到收集到完整的行。所以这个流可以通过使用 BufferedInputStream 作为它的源来加速,这样该行的字节是从内存缓冲区中读取的,而不是直接从磁盘中读取的。

于 2009-11-12T11:21:42.470 回答
4

使用非缓冲 I/O,每个读取或写入请求都直接传递给操作系统。Java 的缓冲 I/O 流读取和写入数据到它们自己的内存缓冲区(通常是字节数组)。仅当缓冲区为空(执行读取时)或缓冲区已满(执行写入时)时才调用操作系统。有时在应用程序的关键点之后手动刷新缓冲区是个好主意。

由于操作系统 API 调用可能会导致磁盘访问、网络活动等,这可能会非常昂贵。使用缓冲区将本机操作系统 I/O 批处理成更大的块通常会显着提高性能。

于 2009-11-12T11:05:26.810 回答
2

缓冲流通过 – nomen est omen – buffering以更大的块写入或读取数据。根据底层流,这可以显着提高性能。

来自java.io.BufferedOutputStream的 Javadocs:

通过设置这样的输出流,应用程序可以将字节写入底层输出流,而不必为每个写入的字节调用底层系统。

于 2009-11-12T10:50:55.523 回答
0

为了减少这种开销,Java 平台实现了缓冲 I/O 流。缓冲输入流从称为缓冲区的内存区域读取数据;仅当缓冲区为空时才调用本机输入 API。类似地,缓冲输出流将数据写入缓冲区,并且仅当缓冲区已满时才调用本机输出 API。

于 2013-06-12T12:40:38.667 回答