Java I / O中的“ Stream”和“ Buffer”到底是什么意思?


82

我刚刚使用了解了输入/输出BufferedReader

我想知道究竟是什么术语的含义StreamBuffer

这行代码还为我们提供了什么:

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

Answers:


201

Java有两种用于输入和输出(I / O)的类:读取器/写入

流(InputStreamOutputStream以及延伸这些一切)用于读取和文件,网络或任何其他设备写入二进制数据。

读者和作家用于阅读和书写文本(字符)。它们是流之上的一层,它使用字符编码将二进制数据(字节)转换为字符,再转换回字符

从磁盘逐字节读取数据效率很低。加快速度的一种方法是使用缓冲区:不是一次读取一个字节,而是一次读取几千个字节,然后将它们放入内存的缓冲区中。然后可以一一查看缓冲区中的字节。

Oracle的有关I / O的Java教程对此进行了详细说明。

查看您提供的代码行:

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

System.in是一个InputStream。您创建了一个InputStreamReader从读取字节的System.in。然后,将其包装在中BufferedReader

因此,最后,您有一个BufferedReaderInputStreamReader读取的从读取的System.in


1
谢谢您的回答,但我感到困惑。正如您所说,我们一次读取数千个字节并将其放入缓冲区;这是否意味着缓冲区只是我们存储事物的内存中的一个地方?
user122345656

3
@Jesper。您说:“加快速度的一种方法是使用缓冲区:不是一次读取一个字节,而是一次读取数千个字节,然后将它们放入内存的缓冲区中。然后您可以查看字节在缓冲区中一一对应。” 是的,它是真的,但是我认为也使用缓冲区,一次读取一个字节。唯一的区别是,我认为将其放在缓冲区中,然后程序从缓冲区而不是磁盘中读取它
M Sach 2013年

7
@ user122345656是的,缓冲区是内存中用于临时存储数据的位置。
Jesper

14
@MSach想想当您想从硬盘读取数据时会发生什么。要在某个位置读取字节,必须等待磁盘旋转,直到磁头位于磁盘上要读取的字节所在的位置上方。如果您当时只读取1个字节,然后再读取下一个字节,则必须等到磁盘旋转一整周才能读取下一个字节。读取连续字节块的效率要高得多。
Jesper

2
@parsecer流用于读取字节;读者用于阅读文本(字符)。InputStreamReader是的封装InputStream,可让您从中读取文本InputStream。如果您只想读取字节(而不是字符),则不需要InputStreamReader。如果要将字节解释为文本字符,则很有用。
杰斯珀,

19

缓冲:

它是物理内存存储用于在数据从一个位置移动到另一位置时临时存储数据。在大多数情况下,该物理内存存储将是RAM(随机存取存储器)。

但是从这个问题的上下文来看,在读取/写入数据时会使用Buffer。将数据从一个位置移动到另一位置时,无需使用它。

缓冲区示例:如果您的系统具有4 GB的RAM,则系统可以为Buffer分配4 KB的内存(RAM)。KB-千字节,GB-千兆字节

I / O流(或流):

I / O流代表输入源或输出目的地。流可以表示许多不同种类的源和目标,包括磁盘文件,设备,其他程序和内存阵列。

I / O表示输入/输出。

因此,Input Stream可以是输入源,例如磁盘文件,网络连接等。

并且,Output Stream可以是输出目标,例如磁盘文件,网络连接等。

根据JAVA的官方文档,流分为3种类型。

  1. 字节流(读或写字节)
  2. 字符流(读取或写入字符)
  3. 缓冲流(为提高效率而从Buffer读取或写入Buffer

字节流:

它们执行8位字节的输入和输出。所有字节流类都从InputStreamOutputStream继承。

字节输入流类获取输入作为原始字节。字节输出流类将输出作为原始字节提供

InputStream-直接已知的子类

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream.

OutputStream-直接已知的子类

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

字符流: 它们是字节流之上的一层。它们使用字符编码将字节(二进制数据)转换为字符,并将字符转换为字节。

所有字符流类均来自ReaderWriter

Reader -直接已知的子类

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer -直接已知的子类

BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter

字节流和字符流使用无缓冲I / O

这意味着每个读取或写入请求均由基础操作系统直接处理。由于每个这样的请求通常会触发磁盘访问,网络活动或其他相对昂贵的操作,因此这会使程序的效率大大降低。为了减少这种开销,Java平台实现了缓冲的I / O流。

缓冲流:

缓冲的输入流称为缓冲区的存储区读取数据;仅当缓冲区为空时才调用本机输入API。

类似地,缓冲的输出流将数据写入缓冲区,并且仅在缓冲区已满时才调用本机输出API。

程序可以使用包装惯例将未缓冲的流转换为缓冲的流,其中将未缓冲的流对象传递给缓冲流类的构造函数。

例:

inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));

有4种缓冲流类,用于包装无缓冲流:

要创建缓冲的 字节流,请使用BufferedInputStreamBufferedOutputStream类。

要创建缓冲的 字符流,请使用BufferedReaderBufferedWriter类。


1
我一直在寻找有关Java io的深入解释。非常感谢你。
阿里夫·雷扎

14

嗯,这是每个人都开始关注java.io包的人的一个问题。为了回答您的问题,InputStreamReader和BufferedReader仅代表Java对象(它们没有什么特别的),但是它们是为io操作而创建的,例如读写不同文件/对象等不同输入/输出的操作

现在开始

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

InputStreamReader是读取字节输入流的类,但是读取每个字节是昂贵的操作,因此我们将其包装在BufferedReader周围以进行缓冲(这是装饰器模式)

因此,即使在您开始读取之前,发生的事情也会发生,bufferedReader会在执行读取操作时在寄存器中存储一些字节块。从该位置读取它比从控制台/文件读取要便宜得多,但是对于InputStreamReader,每次执行磁盘访问操作时执行读取操作


+1,但我希望为信息装饰器添加链接参考,并且每次进行磁盘访问操作时都会产生
情感

最后一段总结了这些好处。谢谢你
Dave Voyles,2015年

3

流是在点之间传递的连接和实际信息。缓冲区是一个存储容器,用于存储部分或全部流数据并将其馈送到输出设备。

当然,要点是,如果流的速度超过了显示数据所需的数据速率,则输出将暂停。缓冲区可以防止这种情况。


感谢ans。但是我想到的一个问题是,流数据意味着什么?请Plz对此进行详细说明。
user122345656

1
这么晚才回复很抱歉。如果您想象服务器上10Mb文件的简单示例。服务器具有完整的文件,但不能在一个数据包中发送整个文件。而是将文件拆分为有限数量的块。然后将每个块发送到远程计算机,然后重新组装。对于流实时数据,采用相同的理论。但是服务器获取实时数据并将其作为stream数据包发送。然后,远程计算机将每个数据包存储在缓冲区中。远程计算机从其缓冲区读取数据,并据此创建视频。我希望这有帮助!
PGallagher

1

缓冲区是内存中用于存储来自外围设备的数据流的一部分。然后从该缓冲区中收集此数据流并将其存储在变量中。流可以定义为连续的数据流。

术语“输入/输出”仅意味着将数据移入和移出缓冲区。只要时刻牢记这一点即可。进程通过请求操作系统从缓冲区中清空数据(写操作)或向缓冲区中填充数据(读操作)来执行I / O。
数据如何移动的逻辑图

简单来说,想象一下当您在键盘上键入数据时,数据通过管道()移动到缓冲区,然后从缓冲区移动到磁盘(写操作)。同样,当数据从磁盘移到缓冲区,再从缓冲区移到控制台时,它就是读操作。

您可以阅读链接以更好地理解。希望能帮助到你!。
Java中的缓冲区是什么,请在
此处输入链接描述

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.