字节流和字符流

流是对 I/O 操作的形象描述,水从一个地方转移到另一个地方就形成了水流,而信息从一处转移到另一处就叫做 I/O 流。

在 Java 中,文件的输入和输出是通过流(Stream)来实现的,流的概念源于 UNIX 中管道(pipe)的概念。在 UNIX 系统中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。

一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是 Internet 上的某个 URL。对于流而言,不用关心数据是如何传输的,只需要从源端输入数据(读),向目的端输出数据(写)。

输入流示意图如下所示:

图片描述

输出流示意图如下所示:

图片描述

输入流的抽象表示形式是接口 InputStream;输出流的抽象表示形式是接口 OutputStream

JDK 中 InputStreamOutputStream 的实现就抽象了各种方式向内存读取信息和向外部输出信息的过程。之前常用的 System.out.println(); 就是一个典型的输出流,目的是将内存中的数据输出到控制台。而 new Scanner(System.in); 就是一个典型的输入流,目的是将控制台接收的信息输入到内存中。 System.inSystem.out 两个变量实际就是 InputStreamOutputStream 的实例对象。以 InputStream 对象为例,如下是定义 System 的源码。

public final class System {
    ...
    public final static InputStream in = null;
    ...
}

字节流和字符流

按照处理数据的单位,流可以分为字节流和字符流。字节流的处理单位是字节,通常用来处理二进制文件,如音乐、图片文件等,并且由于字节是任何数据都支持的数据类型,因此字节流实际可以处理任意类型的数据。而字符流的处理单位是字符,因为 Java 采用 Unicode 编码,Java 字符流处理的即 Unicode 字符,所以在操作文字、国际化等方面,字符流具有优势。

字符流和字节流只是适应于不同的文件类型,并没有效率高低之分。

字节流的输入输出类

输入字节流类继承自抽象类 InputStream,输出字节流继承自抽象类 OutputStream,这两个抽象类拥有的方法可以通过查阅 Java API 获得。

JDK 提供了不少字节流的实现类,下面列举了六个输入字节流类,输出字节流类和输入字节流类存在对应关系。

  • FileInputStream:把一个文件作为输入源,从本地文件系统中读取数据字节,实现对文件的读取操作。
  • ByteArrayInputStream:把内存中的一个缓冲区作为输入源,从内存数组中读取数据字节。
  • ObjectInputStream:对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化,用于恢复那些以前序列化的对象,注意这个对象所属的类必须实现 Serializable 接口(网络编程会用到)。
  • PipedInputStream:实现了管道的概念,从线程管道中读取数据字节。主要在线程中使用,用于两个线程间的通信。
  • SequenceInputStream:其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直至到达文件末尾,接着从第二个输入流读取,依次类推。
  • System.in:从用户控制台读取数据字节,在 System 类中,in 是 InputStream 类型的静态成员变量。

字符流的输入输出类

读取字符流类继承自抽象类 Reader,写入字符流继承自抽象类 Writer。并且 Reader 的子类必须实现的方法只有 read(char[], int, int)close()。但是,多数子类还重写了 WriterReader 类定义的一些其他方法,以提供更高的效率或完成其他功能。

ReaderWriter 要解决的一个主要问题是国际化。原先的 I/O 类库只支持 8 位的字节流,因此不能很好地处理 16 位的 Unicode 字符。Unicode 是国际化的字符集,这样在增加了 ReaderWriter 之后,就可以自动在本地字符集和 Unicode 国际化字符集之间进行转换,程序员在应对国际化时不需要做过多额外的处理。

JDK 提供了一些字符流实现类,下面列举了部分输入字符流类,同样,输出字符流类和输入字符流类存在对应关系。

  • FileReader :与 FileInputStream 对应,从文件系统中读取字符序列。
  • CharArrayReader :与 ByteArrayInputStream 对应,从字符数组中读取数据。
  • PipedReader :与 PipedInputStream 对应,从线程管道中读取字符序列。
  • StringReader :从字符串中读取字符序列。

Writer 输出字符流的可用方法。注意,这些方法操作的数据是 char 相关类型,不是 byte 类型。

  • Writer append(char c):将指定字符 c 追加到此 Writer,此处是追加,不是覆盖。
  • Writer append(CharSequence csq):将指定字符序列 csq 添加到此 Writer。
  • Writer append(CharSequence csq, int start, int end):将指定字符序列 csq 的子序列,追加到此 Writer。
  • void write(char[] cbuf):写入字符数组 cbuf。
  • void write (char[] cbuf, int off, int len):写入字符数组 cbuf 的某一部分。
  • void write(int c):写入单个字符 c。
  • void write(String str):写入字符串 str。
  • void write(String str, int off, int len):写入字符串 str 的某一部分。
  • void close():关闭当前流。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值