"流"和"缓冲区"究竟在Java I/O中意味着什么?

use*_*656 76 java buffer bufferedreader

我刚刚学习了输入/输出BufferedReader.

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

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

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Run Code Online (Sandbox Code Playgroud)

Jes*_*per 188

Java有两种输入和输出类(I/O):读/写器.

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

读者和作者用于阅读和书写文字(字符).它们是流的顶层,使用字符编码将二进制数据(字节)转换为字符并返回.

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

Oracle 关于I/O的Java教程详细解释了它.

查看您提供的代码行:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Run Code Online (Sandbox Code Playgroud)

System.in是一个InputStream.您创建一个InputStreamReader从中读取字节System.in.然后你把它包装成一个BufferedReader.

所以,最后,你有一个BufferedReader从中读取的InputStreamReader内容System.in.

  • @MSach想想当你想从硬盘读取数据时会发生什么.要读取某个位置的字节,必须等到磁盘旋转,直到磁头位于磁盘上要读取的字节所在的位置.如果此时只读取1个字节,后一个字节读取,则必须等到磁盘完全旋转才能读取下一个字节.读取连续字节块的效率要高得多. (12认同)
  • @ user122345656是的,缓冲区是内存中临时存储数据的地方. (7认同)
  • 很好地解释了! (4认同)
  • @Jesper.你说"加速它的一种方法是使用缓冲区:不是一次读取一个字节,而是一次读取几千个字节,然后将它们放在内存中的缓冲区中.然后你可以查看字节在缓冲区一个接一个." 是的它是真的,但我认为缓冲区也是,一次读取单字节.唯一的区别我认为它放在缓冲区和程序然后从缓冲区而不是磁盘读取它 (3认同)
  • 谢谢您的回答,但我有一个困惑。正如您所说,我们一次读取几千个字节并将它们放入缓冲区中;那么这是否意味着缓冲区只是内存中我们存储内容的地方? (2认同)
  • @parsecer Streams 用于读取字节;reader 用于阅读文本(字符)。`InputStreamReader` 是 `InputStream` 的包装器,它允许您从 `InputStream` 中读取文本。如果您只想读取字节(而不是字符),则不需要 `InputStreamReader`。如果您想将字节解释为文本字符,这很有用。 (2认同)

M S*_*ach 14

那是一个在everbodys头脑中开始研究java.io包的问题.要回答你的问题,术语InputStreamReader和BufferedReader只代表java对象(没有什么特别之处)但它们是为io操作创建的,比如从/向不同的输入/输出(如文件,对象等)读取和写入

现在让我们来吧

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Run Code Online (Sandbox Code Playgroud)

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

因此,即使在开始读取之前,bufferedReader将在寄存器中存储一些字节并执行读取操作.它将从该位置读取,这比从控制台/文件读取便宜得多但是在InputStreamReader的情况下,每次执行磁盘访问操作时执行读取操作


AnV*_*AnV 14

缓冲:

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

但是从这个问题的上下文中,在读/写数据时使用了Buffer.将数据从一个地方移动到另一个地方时不需要使用它.

缓冲区示例:如果您的系统有4 GB RAM,则系统可以为缓冲区分配4 KB内存(RAM).KB - Kilobyte(s),GB - Gigabyte(s)

I/O流(或)流:

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

I/O表示输入/输出.

因此,输入流可以是磁盘文件,网络连接等输入源.

并且,输出流可以是输出目的地,如磁盘文件,网络连接等.

根据JAVA官方文档,Streams有3种类型.

  1. 字节流(读取或写入字节)
  2. 字符流(读或写字符)
  3. 缓冲流(从缓冲区读取或写入,以提高效率)

字节流:

它们执行8位字节的输入和输出.所有字节流类都来自InputStreamOutputStream.

字节输入流类获取输入作为原始字节.字节输出流类将输出作为原始字节.

InputStream- 直接已知子类

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream.
Run Code Online (Sandbox Code Playgroud)

OutputStream- 直接已知子类

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream
Run Code Online (Sandbox Code Playgroud)

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

所有字符流类都来自ReaderWriter.

Reader - 直接已知子类

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
Run Code Online (Sandbox Code Playgroud)

Writer - 直接已知子类

BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter
Run Code Online (Sandbox Code Playgroud)

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

这意味着每个读取或写入请求都由底层操作系统直接处理.这可以使程序效率低得多,因为每个这样的请求经常触发磁盘访问,网络活动或一些相对昂贵的其他操作.为了减少这种开销,Java平台实现了缓冲的I/O流.

缓冲流:

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

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

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

例:

inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));
Run Code Online (Sandbox Code Playgroud)

有4个缓冲流类用于包装无缓冲的流:

要创建缓冲的 字节流使用BufferedInputStreamBufferedOutputStream类.

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