Java之I/O流

版权声明:转载请注明出处 https://blog.csdn.net/qq_41431457/article/details/86521412
  • 前言

       一个好的程序语言,完善的输入输出功能是必不可少的。在Java中将不同来源和目标的数据统一抽象为流,通过对流对象的操作来完成I/O功能。Java中的流很灵活,可以连接到各种不同的源或目标,如磁盘文件、键盘(输入设备)、显示器(输出设备)、网络等。


  • 流的层次

       Java中所有的I/O都是通过流来实现的,可以将流理解为连接到数据目标或源的管道,可以通过连接到源的流从源当中读取数据,或通过连接到目标的流向目标中写入数据,根据流的方向可以将其分为两类:输入流和输出流。用户可以从输入流中读取信息,向输出流中写信息。根据流处理的数据类型不同也可以将其分为两类:字节流和字符流 。下面主要从类的层次来介绍I/O流。

       Java中I/O流是由java.io包来实现的,其中的类大致分为输入和输出两大部分。在java.io包最顶层包含子类较多的两个类是InputStream和OutputStream。下图分别表示java.io包中的输入流类和输出流类的层次。这两个类均为抽象类,也就是说不能创建它们的实例对象,必须创建子类之后才能建立对象。java.io包中很多类都是从这两个类继承而来的,因此这些子类有很多相同的方法。

InputStream继承Object类,如图1所示,有7个类直接继承InputStream,其中子类FilterInputStream本身又是一个具有4个子类的抽象类。

图1

OutputStream也是继承Object类,如图2所示,有5个类直接继承OutputStream,其中子类FilterOutputStream本身又是一个具有3个子类的抽象类。

图2

java.io包顶层除了图1和图2两个类外,还包括如下一些流类:

1、File类

       File类代表一个操作系统文件,功能十分强大。利用File类可以为操作系统文件创建一个File对象(目录或文件),也可以访问指定文件的所有属性,包括它的完整路径名称、长度、文件的最后修改时间,还可以建立目录和名称。

2、Reader和Weiter类

       由于Java采用16位的Unicode字符,因此需要基于字符的输入和输出操作,从java1.1开始,加入了专门处理字符的抽象类,Reader类和Weiter类,从类的层次来看,它们与InputStream和OutputStream类似,也有很多子类,用来对具体的字符流对象进行I/O流操作。

3、RandomAccessFile类

       AandomAccessFile代表一个随机访问文件,通过构造RandomAccessFile类,可以对文件进行访问操作。

此外,java.io包还定义了一下3个接口:

1、DataInput和DateOutput

       这两个接口说明,可以使用与机器无关的数据格式读写简单数据类型的输入和输出流。DataInputStream、DataOutputStream和RandomAccessFile实现这两个接口。

2、FilenameFilter

       它是针对文件名的过滤性接口。File类中的list()方法可以使用FilenameFilter来确定一个目录的哪些文件需要列出,哪些文件将被排除。还可以通过FilenameFilter实现文件的匹配查找,如查找abc.*等。


  • 输入流和输出流

       前面介绍过,java的I/O类库分成输入和输出两大部分。所有InputStream和Reader的派生类都具有一个继承下来的,能读取单个或byte数组的read()方法。同理,所有OutputStream和Writter的派生类都有一个能写入单个或byte数组的write()方法。但通常情况下,这些方法不是直接应用的,而是供其他类使用,而其他类会提供一些更实用的接口。java的设计者们遵循这样的原则:让所有的与输入相关的类去继承InputStream,所有与输出相关的类继承OutputStream。

       下面根据功能对这些流进行归类。

1、InputStream类

InputStream类的主要任务就是代表哪些能从各种输入源获取数据的类。这些源包括以下几种:

  1. byte数组
  2. String对象
  3. 文件
  4. 类似流水线的“管道(pipe)”。把东西从一头放进去,让它从另一头出来。
  5. 一个“流的序列(A sequence of other streams )”,可以将它们组成一个单独的流
  6. 其他源如Inerter的连接

       这些数据源各自都有与之对应的InputStream子类。此外,FilterInputStream也是InputStream的子类,其作用是为基类提供“decorator (修饰)”类,而decorator又是为InputStream配置属性和接口的。

下表列出了InputStream类系中的主要一些子类:

表1:

InputStream类系
功能 构造函数的参数 用法
ByteArrayInput-Stream 以缓冲区内存为InputStream 要从中提取byte的那个缓冲区 一种数据源:要把它连接到FilterInputStream对象,由后者提供接口
StringBufferInput-Stream 以String为InputStream 需要一个String对象。实际上程序内部用的都是String-Buffer 一种数据源:要把它连接到FilterInputStream对象,由后者提供接口
FileInputStream 专门用来读文件 一个表示文件名的String对象,也可以是File或File-Descriptor对象 一种数据源:要把它连接到FilterInputStream对象,由后者提供接口
PipedInputStream 从PipedOutputStream提取数据,实现“管道”功能 PipedOutputStream 一种多线程环境下的数据源,把它连接到FilterInputStream对象,由后者提供接口
SequenceInput-Stream 将两个或更多的InputStream合并成一个InputStream 两个InputStream对象,或一个InputStream对象容器的Enumerator 一种数据源:要把它连接到FilterInputStream对象,由后者提供接口
FilterInputStream 一个给decorator提供接口的抽象类。而decorator的作用是为OutputStream实现具体功能 表5进行说明 表5进行说明

2、OutputStream类系

       OutputStream类系都是决定向哪里输出的类:byte的数组(不能是String,不过可以根据byte数组创建字符串)、文件或者“管道”。

另外,FilterOutputStream也是decorator类的基类。它会为OutputStream安装属性和适用的接口。

下表列出了OutputStream类系的主要一些类:

OutputStream类系
功能 构造函数的参数 用法
ByteArrayOutput-Stream 在内存中创建一个缓冲区。数据送到流里就是写入这个缓冲区 缓冲区初始大小,可选 要想为数据制定目标,可以用FilterOutput Stream对其进行包装,并提供接口
FilterOutput Stream 将数据写入文件 一个表示文件名的字符串,也可以是File或FileDescriiptor对象 要想为数据制定目标,可以用FilterOutput Stream对其进行包装,并提供接口
PipedOutputStream 写入这个流的数据,最终都会成为与之相关联的PipeInput-Stream的数据源。否则就不称其为“管道”了 PipedInputStream 要想在多线程环境下为数据指定目标,可以用FilterOutputStream对其进行包装,并提供接口
FilterOutputStream 一个给decorator提供接口用的抽象类。而decorator作用是为OutputStream实现具体的功能 表6详细说明 表6详细说明

3、Reader类系和Writer类系

       第一次看见Reader和Writer的时候,可能会觉得它们大概是用来取代InputStream和OutputStream的,但事实并非如此。

       虽然Input Stream和Output Stream的某些功能已经淘汰(如果继续使用,编译会报错),但他们任然提供了很多有价值的,面向byte的I/O功能,而Reader和Writer则提供了Unicode兼容的,面向字符的I/O功能。Reader和Writer类系的类读写基于字符的数据,这种数据比字节级数据更为单一化、标准化,所以字符级输入类也能读取和解释标准的文本编辑器的数据。而字符级输出流写入的数据也能用于其他应用程序,如标准文本编辑器。这些类的应用也是相对的,大多数写数据的输出类,都有相应的读数据的输入类。

基于字符数据的输出流
类名 功能描述
Writer 字符流的抽象类
BufferedWriter 经过字符缓冲将文本写道一个字符输出流中
Print Writer 打印格式化对象内容到文本输出流中。这个类的方法并不抛出I/O异常,但客户可以用checkError方法检查是否出错
OutputStreamWriter 从字符流到字节流的桥梁:它能将字符转换为字节,然后将字节写入流
FileWriter 能方便的写字符文件
 基于字符数据的输入流
类名 功能描述
Reader 读字符流的抽象类
BufferReader 从字符输入流中读文本,可在必要时缓冲字符
LineNumberReader 一个能记录行数的缓冲字符输入流
InputStreamReader 从字节流到字符流的桥梁:它能读字节并把它转换为字符
FileReader 能方便的读字符文件

4、输入流和输出流的过滤

       前面提到对输入流和输出流可以过滤,过滤输入流FilterInputStream与过滤输出流FileOutputStream实现该功能。它们的主要作用是在输入/输出数据的同时能对传输数据做指定格式或类型的转换,也就是说可实现对二进制字节数据的编码转换。

FileInputStream相关的类
功能 构造函数 用法
DataInput-Stream 与DataOutputStream配合使用,这样就能以一种“可携带的方式(portable-fashion)”从流里读取primitives数据(int、char等) InputStream 包含了一整套读取primitive数据的接口
BufferedInput-Stream 用这个类来解决“每次使用数据的时候都要进行物理读取”的问题。通过缓冲区来解决 InputStream以及可选的缓冲区的容量 它本身并不提供接口,只是提供一个缓冲区。需要连到一个“有接口的对象”
LineNumberIn-put Stream 跟踪输入流的行号,有getLine-Number()和setLine Number(int)方法 InputStream 只是加一个行号,所以还要连接一个“有接口的对象”
PushbackInput-Stream 有一个“弹压单字节”的缓冲区(has a one byte push-back buffer),这样就能把最后读到的那个字节再压回去了 InputStream 主要用于编译器的扫描程序。可能是为支持java的编译器而设计的。使用的机会并不多
FileOutputStream相关的类
功能 构造函数的参数 用法

DataOutput-Stream

与DataInputStream配合使用,这样就可以用一种“可携带的方式(portable fashion)”网流里写primitive数据 Output Stream 包括写入primitive数据的全套接口
PrintStream 负责生成带格式的输出(formatted-output)。DataOutput Stream负责数据的存储,而PrintStream负责数据的显示 一个OutputStream以及一个可选的Boolean值。这个boolean表示要不要清空换行符后面的缓冲区 应该是OutputStream对象的最终包覆层。用的机会很多
BufferOutput-Stream 用这个类解决“每次向流里写入数据,都要进行物理操作”的问题。用flush()清空缓冲区 OutputStream,以及一个可选的缓冲区大小 本身并不提供接口,只是加了一个缓冲区。需要连接一个有接口的对象

猜你喜欢

转载自blog.csdn.net/qq_41431457/article/details/86521412