Java IO包体系结构图:
1.流式部分――IO的主体部分;
2.非流式部分——主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类;
3.其他类——文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要的类如下:
1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
4. Reader(文件格式操作):抽象类,基于字符的输入操作。
5. Writer(文件格式操作):抽象类,基于字符的输出操作。
6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
IO流类结构图:
1、流的概念和作用
流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接受端对象<Thing in Java>
流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作
流的作用:为数据源和目的地建立一个输送通道。
Java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流.
2、Java IO所采用的模型
Java的IO模型设计非常优秀,它使用Decorator(装饰者)模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。
例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。
3、IO流的分类
· 根据处理数据类型的不同分为:字符流和字节流
· 根据数据流向不同分为:输入流和输出流
· 按数据来源(去向)分类:
1、File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter
2、byte[]:ByteArrayInputStream, ByteArrayOutputStream
3、Char[]: CharArrayReader,CharArrayWriter
4、String:StringBufferInputStream, StringReader, StringWriter
5、网络数据流:InputStream,OutputStream, Reader, Writer
字符流和字节流
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
1) 字节流:数据流中最小的数据单元是字节
2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
字符流的由来: Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
输入流和输出流
根据数据的输入、输出方向的不同对而将流分为输入流和输出流。
1) 输入流:程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道
2) 输出流:程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。
采用数据流的目的就是使得输出输入独立于设备。
输入流( Input Stream )不关心数据源来自何种设备(键盘,文件,网络)。
输出流( Output Stream )不关心数据的目的是何种设备(键盘,文件,网络)。
3)特性
相对于程序来说,输出流是往存储介质或数据通道写入数据,而输入流是从存储介质或数据通道中读取数据,一般来说关于流的特性有下面几点:
1、先进先出,最先写入输出流的数据最先被输入流读取到。
2、顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile可以从文件的任意位置进行存取(输入输出)操作)
3、只读或只写,每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。
4、Java IO流对象
1.输入字节流InputStream
1) FileInputStream:文件输入流,从本地文件系统中获取输入字节。
2) FilterInputStream:过滤器字节输入流,这里不得不提到一种设计模式:Decorator(装饰者)模式,它的主要用途在于给一个对象动态的添加一些额外的职责。与生成子类相比,它更具有灵活性。
BufferedInputStream:缓冲输入流,为另一个输入流添加了功能,即缓冲输入和支持mark
和reset
方法的功能。
DataInputStream:数据输入流,允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。
PushbackInputStream:将功能添加到另一个输入流,即可以“推回”或“未读”一个字节。
3) ObjectInputStream:反序列化先前使用ObjectOutputStream编写的原始数据和对象。
4) PipedInputStream:管道输入流,它的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。
5) SequenceInputStream:表示其他输入流的逻辑级联。 它从一个有序的输入流集合开始,从第一个读取到文件的结尾,然后从第二个文件读取,依此类推,直到最后一个输入流达到文件的结尾。
6) StringBufferInputStream 已弃用(此类不会将字符正确转换为字节),允许应用程序创建一个输入流,其中读取的字节由字符串的内容提供。
7) ByteArrayInputStream:包含一个内部缓冲区,其中包含可以从流中读取的字节。 内部计数器跟踪read
方法要提供的下一个字节。
2.输出字节流OutputStream
与输入字节流相对应
3.输入字符流
1) BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
2) InputStreamReader:从字节流到字符流的桥:它读取字节,并使用指定的charset
将其解码为字符 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
FileReader:用于读取字符流。
3) StringReader:一个字符流,其源是一个字符串,对字符串进行操作。
4) PipedReader:PipedReader和PipedWriter即管道输入流和输出流,可用于线程间管道通信。它们和PipedInputStream/PipedOutputStream区别是前者操作的是字符后者是字节。
5) CharArrayReader:该类实现了一个字符缓冲区,可以用作字符输入流。
6) FilterReader:过滤器字符输入流,同样用到了Decorator(装饰者)设计模式
PushbackReader:一个字符流读取器,允许将字符推回到流中。
4.输出字符流
与输入字符流相对应
五、字符流与字节流的转换
转换流的特点:
1. 其是字符流和字节流之间的桥梁
2. 可对读取到的字节数据经过指定编码转换成字符
3. 可对读取到的字符数据经过指定编码转换成字节
何时使用转换流?
1. 当字节和字符之间有转换动作时;
2. 流操作的数据需要编码或解码时。
具体的对象体现:
转换流:在IO中还存在一类是转换流,将字节流转换为字符流,同时可以将字符流转化为字节流。
1. InputStreamReader:字节到字符的桥梁
2. OutputStreamWriter:字符到字节的桥梁
OutputStreamWriter(OutStreamout):将字节流以字符流输出。
InputStreamReader(InputStream in):将字节流以字符流输入。
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。
六、字节流和字符流的区别
字节流和字符流的区别:
字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。
· 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
· 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流。