Java 7源码分析第12篇 - 输入输出流

本文详细介绍Java中I/O流的分类与应用,包括字节流与字符流两大类,并进一步细分为输入流与输出流。文章列举了各种流的具体用途、构造方式及其使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。Java的I/O操作类在java.io包下,这些类可以大概分为两类,操作字节流的和操作字符流的类:
(1)字节流
表示以字节为单位从stream中读取或往stream中写入信息,即io包中的inputstream类和outputstream类的派生类。通常用来读取二进制数据,如图象和声音。
(2)字符流

以Unicode字符为单位从stream中读取或往stream中写入信息。


1、字节输入流


下面来看一下操作字节输入流的类的框架结构:


可以看到:

1.InputStream是所有的输入字节流的父类,它是一个抽象类。

2. ByteArrayInputStreamStringBufferInputStreamFileInputStream是三种基本的介质流,它们分别将Byte数组、StringBuffer、和本地文件中读取数据。PipedInputStream是从与其它线程共用的管道中读取数据。
3. ObjectInputStream和所有FilterInputStream的子类都是装饰流。

详细的介绍如下:


功能

如何构造

怎样使用

ByteArrayInputStream

将内存中的Byte数组适配为

一个InputStream

从内存中的Byte数组创建该对象(2种方法)

一般作为数据源,会使用其它装饰流提供额外的功能,一般都建议加个缓冲功能。

StringBufferInputStream

将内存中的字符串适配为一

InputStream

从一个String对象创建该对象。底层的实现使用StringBuffer。该类被Deprecated

主要原因是StringBuffer不应该属于字节流,所以推荐使用StringReader

一般作为数据源,同样会使用其它装饰器提供额外的功能。

FileInputStream

最基本的文件输入流。主要

用于从文件中读取信息。

通过一个代表文件路径的StringFile对象或者FileDescriptor对象创建。

一般作为数据源,同样会使用其它装饰器提供额外的功能。

PipedInputStream

读取从对应PipedOutputStream

写入的数据。在流中实现了管道的概念。

利用对应的PipedOutputStream创建。

在多线程程序中作为数据源,同样会使用其它装饰器提供额外的功能。

SequenceInputStream

2个或者多个InputStream对象转

变为一个InputStream.

使用两个InputStream或者内部对象为InputStreamEnumeration对象创建该对象。

一般作为数据源,同样会使用其它装饰器提供额外的功能。

FilterInputStream

给其它被装饰对象提供额外功能的抽

象类

主要子类见下表

在FilterInputStream类下还有一些具体的子类,如下图:



功能

如何构造

怎样使用

DataInputStream

一般和DataOutputStream配对使用,完成基本数据类型的读写。

利用一个InputStream构造。

提供了大量的读取基本数据类新的读取方法。

BufferedInputStream

使用该对象阻止每次读取一个字节都会频繁操作IO

将字节读取一个缓存区,从缓存区读取。

利用一个InputStream、或者带上一个自定义的缓存区的大小构造。

使用InputStream的方法读取,只是背后多一个缓存的功能。

LineNumberInputStream

跟踪输入流中的行号。可以调用getLineNumber()

setLineNumber(int)方法得到和设置行号。

利用一个InputStream构造。

紧紧增加一个行号。可以象使用其它InputStream一样使用。

PushbackInputStream

可以在读取最后一个byte后将其放回到缓存中。

利用一个InputStream构造。

一般仅仅会在设计compilerscanner时会用到这个类。一般很少用到。


2、字节输出流


看一下操作字节输出流的类的框架结构:


可以看到:

1.OutputStream是所有的输出字节流的父类,它是一个抽象类。

2. ByteArrayOutputStreamFileOutputStream是两种基本的介质流,它们分别向Byte数组、和本地文件中写入数据。PipedOutputStream是向与其它线程共用的管道中写入数据,

3. ObjectOutputStream和所有FilterOutputStream的子类都是装饰流。下表列出了输出字节流的功能及如何使用它们。

来看一下各个类的具体介绍:


功能

如何构造

怎样使用

ByteArrayOutputStream

在内存中创建一个buffer。所有写

入此流中的数据都被放入到此buffer中。

无参或者使用一个可选的初始化buffer的大小的参数构造。

一般将其和FilterOutputStream套接得到额外的功能。建议首先和BufferedOutputStream

套接实现缓冲功能。通过toByteArray方法可以得到流中的数据。

FileOutputStream

将信息写入文件中。

使用代表文件路径的StringFile对象或者FileDescriptor对象创建。还可以加一个代表写

入的方式是否为append的标记。

一般将其和FilterOutputStream套接得到额外的功能。

PipedOutputStream

任何写入此对象的信息都被放入对应

PipedInputStream对象的缓存中,

从而完成线程的通信,实现了“管道”

的概念。具体在后面详细讲解。

利用PipedInputStream构造

在多线程程序中数据的目的地的。一般将其和FilterOutputStream套接得到额外的功能。

FilterOutputStream

实现装饰器功能的抽象类。为其它

OutputStream对象增加额外的功能。

见下表

见下表

在FilterOutputStream类下还有一些具体的子类,如下图所示。


功能

如何构造

怎样使用

ByteArrayOutputStream

在内存中创建一个buffer。所有写

入此流中的数据都被放入到此buffer中。

无参或者使用一个可选的初始化buffer的大小的参数构造。

一般将其和FilterOutputStream套接得到额外的功能。建议首先和BufferedOutputStream

套接实现缓冲功能。通过toByteArray方法可以得到流中的数据。

FileOutputStream

将信息写入文件中。

使用代表文件路径的StringFile对象或者FileDescriptor对象创建。还可以加一个代表写

入的方式是否为append的标记。

一般将其和FilterOutputStream套接得到额外的功能。

PipedOutputStream

任何写入此对象的信息都被放入对应

PipedInputStream对象的缓存中,

从而完成线程的通信,实现了“管道”

的概念。具体在后面详细讲解。

利用PipedInputStream构造

在多线程程序中数据的目的地的。一般将其和FilterOutputStream套接得到额外的功能。

FilterOutputStream

实现装饰器功能的抽象类。为其它

OutputStream对象增加额外的功能。

见下表

见下表

3、字符输入流

1.Reader是所有的输入字符流的父类,它是一个抽象类。

2.CharReaderStringReader是两种基本的介质流,它们分别将Char数组、String中读取数据。PipedReader是从与其它线程共用的管道中读取数据。

3. BufferedReader很明显就是一个装饰器,它和其子类负责装饰其它Reader对象。

4.FilterReader是所有自定义具体装饰流的父类,其子类PushbackReaderReader对象进行装饰,会增加一个行号。

5.InputStreamReader是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream转变为Reader的方法。我们可以从这个类中得到一定的技巧。





4、字符输出流



在上面的关系图中可以看出:

1.Writer是所有的输出字符流的父类,它是一个抽象类。

2. CharArrayWriterStringWriter是两种基本的介质流,它们分别向Char数组、String中写入数据。PipedWriter是向与其它线程共用的管道中写入数据,

3. BufferedWriter是一个装饰器为Writer提供缓冲功能。

4.PrintWriterPrintStream极其类似,功能和使用也非常相似。

5.OutputStreamWriterOutputStreamWriter转换的桥梁,它的子类FileWriter其实就是一个实现此功能的具体类(具体可以研究一下Source Code)。功能和使用和OutputStream极其类似,后面会有它们的对应图。



区别:

Reader和Writer要解决的,最主要的问题就是国际化。原先的I/O类库只支持8位的字节流,因此不可能很好地处理16位的Unicode字符流。Unicode是国际化的字符集(更何况Java内置的char就是16位的Unicode字符),这样加了Reader和Writer之后,所有的I/O就都支持Unicode了。此外新类库的性能也比旧的好。

但是,Read和Write并不是取代InputStream和OutputStream,有时,你还必须同时使用"基于byte的类"和"基于字符的类"。为此,它还提供了两个"适配器(adapter)"类。InputStreamReader负责将InputStream转化成Reader,而OutputStreamWriter则将OutputStream转化成Writer。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值