IO流分类:
字节流
InputStream
OutputStream
文件流:
FileInputStream
FileOutputStream
字节缓冲流:
BufferedInputStream
BufferedOutputStream
- flush
对象流:
ObjectInputStream
ObjectOutputStream
序列化:对象à字节序列
Serializable
版本号
反序列化:字节序列à对象
字符流:
Reader
Writer
转换流:
OutputStreamWriter
InputStreamReader
字符缓冲流:
BufferedWriter:
- PrintWriter
- println() //具有行自动刷新功能
BufferedReader
按行读取数据
readLine() - String
字节流
抽象基类:
InputStream
outPutStream
文件流:
是一对低级流(节点流)
FOS:字节输出流,用于写数据
构造方法:
FileOutputStream(File file):
FileOutputStream(String filename):
写数据方法:
Wirte(byte[] bys)
思考:如何向文件中追加写入数据?
FIS:字节输入流
构造方法:
FileInputStream(File file)
FileInputStream(String name)
读取数据:
按单个字节读取,
按字节数组读取
缓冲流
是一对处理流(高级流)
BOS:BufferedOutputStream工作原理
在向硬件设备做写出操作时,增大写出次数无疑会降低写出效率,为此我们可以使用缓冲输出流来一次性批量写出若干数据减少写出次数来提高写出效率。
BufferedOutputStream缓冲输出流内部维护着一个缓冲区,每当我们向该流写数据时,都会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写出。
对象的创建以及写数据
flush方法: 清空缓冲区,将缓冲区中的数据强制写出。
BIS:BufferedInputStream工作原理
在读取数据时若以字节为单位读取数据,会导致读取次数过于频繁从而大大的降低读取效率。为此我们可以通过提高一次读取的字节数量减少读写次数来提高读取的效率。
BufferedInputStream是缓冲字节输入流。其内部维护着一个缓冲区(字节数组),使用该流在读取一个字节时,该流会尽可能多的一次性读取若干字节并存入缓冲区,然后逐一的将字节返回,直到缓冲区中的数据被全部读取完毕,会再次读取若干字节从而反复。这样就减少了读取的次数,从而提高了读取效率。
对象流
读写对象的流:
ObjectOutputStream
ObjectInputStream
对象是存在于内存中的。有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这样的操作。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化。相反,我们有这样一个字节序列需要将其转换为对应的对象,这个过程就称为对象的反序列化。
Serializable接口:
ObjectOutputStream在对对象进行序列化时有一个要求,就是需要序列化的对象所属的类必须实现Serializable接口。
实现该接口不需要重写任何方法。其只是作为可序列化的标志。
序列化 : 对象 -->字节序列
应用场景:1.将对象持久化到磁盘 2.将对象用于网络传输
将对象序列化后写到文件中的内容为:
对象的类型,类的项目信息,包信息,类信息,
成员数据,其他的信息
如果对一个类添加属性或减少属性,对已经写好的对象进行反序列化,出现什么问题?如何解决?
SeriaVersionID:
通常实现该接口的类需要提供一个常量serialVersionUID,表明该类的版本
如果声明的类的对象序列化存到硬盘上面,之后随着需求的变化更改了类的属性(增加或减少或改名),那么当反序列化时,就会出现InvalidClassException,这样就会造成不兼容性的问题。
当一个类实现了Serializable接口后,编译器会提示应当添加一个常量:serialVersionUID,这个常量标识当前类的序列化版本号.若不指定,编译器在编译当前类时会根据当前类的结构生成,但是只要类的结构发生了变化,那么版本号就会改变.版本号决定着一个对象是否可以反序列化成功.
当对象输入流在将一个对象进行反序列化时会检查该对象的版本号与当前程序中这个类的版本号是否一致?
若一致:反序列化成功,若当前类发生了改变,那么则还原依然存在的属性.
若不一致,则反序列化方法readObject会抛出异常.
transient关键字:
当一个属性被transient修饰后,该属性在进行对象序列化时其值会被忽略.
忽略不必要的属性值可以达到对象序列化"瘦身"的效果.
对象的序列化(下)
如果对一个类添加属性或减少属性,对已经写好的对象进行反序列化,出现什么问题?如何解决?
当一个类实现了Serializable接口后,编译器会提示应当添加一个常量:serialVersionUID,这个常量标识当前类的序列化版本号.若不指定,编译器在编译当前类时会根据当前类的结构生成,但是只要类的结构发生了变化,那么版本号就会改变.版本号决定着一个对象是否可以反序列化成功.
SeriaVersionUID:
通常实现该接口的类需要提供一个常量serialVersionUID,表明该类的版本
如果声明的类的对象序列化存到硬盘上面,之后随着需求的变化更改了类的属性(增加或减少或改名),那么当反序列化时,就会出现InvalidClassException,这样就会造成不兼容性的问题。
当对象输入流在将一个对象进行反序列化时会检查该对象的版本号与当前程序中这个类的版本号是否一致,
若一致:反序列化成功,若当前类发生了改变,那么则还原依然存在的属性.
若不一致,则反序列化方法readObject会抛出异常.
public class Person implements Serializable {
private static final long serialVersionUID = -3209447599028837032L;
transient关键字:
当一个属性被transient修饰后,该属性在进行对象序列化时其值会被忽略.
忽略不必要的属性值可以达到对象序列化"瘦身"的效果.
当一个对象是可序列化时,如果内部的成员是别的对象,那么,作为成员的其他对象一定也是可序列化的。
字符流(文本数据IO流)Reader和Writer
Reader:字符输入流的父类
Writer:字符输出流的父类。
字符流是以字符(char)为单位读写数据的。一次处理一个字符。
字符流的底层仍然是基本的字节流。
字符流封装了字符的编码解码算法。
常用方法:
写数据:
write(int c) :写出一个字符
write(char[] chs):将给定的字符数组中的所有字符写出
write(String str):将给定的字符串写出
write(char[] chs,int offset,int len):
将给定的字符数组中从offset处开始连续的len个字符写出
转换流:
Writer和Reader的子类:
OutputStreamWriter
使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流写出。
OutputStreamWriter(OutputStream out,String charsetName)
基于给定的字节输出流以及字符编码创建OSW
OutputStreamWriter(OutputStream out)
该构造方法会根据系统默认字符集创建OSW
InputStreamReader:
使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取。
构造方法:
InputStreamReader(InputStream in,String charsetName)
基于给定的字节输入流以及字符编码创建ISR
InputStreamReader(InputStream in)
该构造方法会根据系统默认字符集创建ISR
字符缓冲流
缓冲字符流:缓冲字符流由于内部有缓冲区,读写字符的效率高.并且字符流的特点是可以按行读写字符串.
BufferedWriter,BufferedReader
PrintWriter也是缓冲字符输出流,它内部总是连接BufferedWriter,除此之外PW还提供了自动行刷新功能.所以更常用.
PrintWriter:缓冲字符输出流
PrintWriter提供了直接对文件进行写操作的构造方法:
PrintWriter(File file)
PrintWriter(String fileName)
若希望按照指定的字符集向文件写出字符串,
可以使用对应重载的构造方法:
PrintWriter(File file,String csn)
PrintWriter(String fileName,String csn)
第二个参数可以指定字符集的名字(charSetName)
方法:
- PrintWriter提供了丰富的重载print与println方法。其中println方法在于输出目标数据后自动输出一个系统支持的换行符。
特点:行自动刷新
当PrintWriter的构造方法第一个参数为流(字节流,字符流均可)时,那么支持一个重载的构造方法可以传入一个boolean值,该值若为true,则当前PrintWriter具有自动行刷新功能,即:每当调用println方法写出一行字符串后会自动调用flush方法将其数据写出. 需要注意,调用print方法是不会flush的
BufferedReader:缓冲字符输入流
BufferedReader是缓冲字符输入流,其内部提供了缓冲区,可以提高读取效率。
BufferedReader的常用构造方法:
BufferedReader(Reader reader)
BufferedReader提供了读取一行字符串的方法:
String readLine()
该方法会连续读取若干字符,直到读取了换行符为止,然后将换行符之间读取到的所有字符以一个字符串形式返回.需要注意,返回的字符串中不包含最后的换行符.当该方法返回null时,表示末尾(不会再读取到任何数据)