BOS基本工作原理
.在向硬件设备作出操作时,增大写出次数无疑会降低写出效率,为此我们可以使用缓冲输出
流来一次性批量写出若干数据减少写出次数来提交写出效率
.BufferedOutputStream缓冲输出流内部维护着一个缓冲区,每当我们向该流写数据时,都
会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写入
BOS实现写出缓冲
public void testBOS() throws Exception{
// 创建输出流对象
FileOutputStream fos = new FileOutputStream("raf.txt");
// 创建缓冲字节输出流
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 所有字节先被存入缓冲区,等待一次性写出
bos.write("select * from world where name = ?".getBytes());
// 关闭流之前,缓冲输出流会将缓冲区内容一次性写出
bos.close();
}
BOS的flush方法
.使用缓冲输出流可以提高写出效率,但是这也存在着一个问题,就是写出数据缺乏即时性,
有时我们需要在执行完某些写出操作后,就希望将这些数据确实写出,而非在缓冲区中保存
直到缓冲区满后才写出,这是我们可以使用缓冲流的一个方法flush
.void flush()
清空缓冲区,将缓冲区的数据强制写出
BIS基本工作原理
.在读取数据时若以字节为单位,会导致读取次数过于频繁,从而大大的降低读取效率.为此
我们可以通过提高一次读取的字节数据量减少读写次数来提高读取的效率
BUfferedInputStream是缓存字节输入流,其内部维护着一个缓冲区(字节数组),
使用该流在读取一个字节时,该流会尽可能多的一次性读取若干字节并存入缓冲区,然后逐一
的将字节返回,直到缓冲区中的数据被全部读取完毕,会再次读取若干字节从而反复,这样
就减少了读取的次数,从而提高了读取效率
.BIS是一个处理流,该流为我们提供了缓冲功能
序列化和反序列化
.对象是存在于内存中的,有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输
到另外一台计算机上等等这样的操作,这时我们需要将对象转换为一个字节序列,而这个过程
就称为对象序列化,相反,我们有这样的一个字节序列需要将其转换为对应的对象,这个过程就
称为对象的反序列化
使用OOS实现对象序列化
.ObjectOutputStream是用来对对象进行序列化的输出流
.其实现对象序列化的方法为:
-void writeObject(Object o)
该方法可以将给定的对象转换为一个字节序列然后输出
使用OIS实现对象反序列化
.ObjectInputStream是用来对对象进行反序列化的输入流
.其实现对象反序列化的方法为:
-Object readObject();
该方法可以从流中读取字节并转换为对应的对象
Serializable接口
.ObjectOutputStream在对对象进行序列化时有一个要求,就是需要序列化的对象所属的类
必须实现Serializable接口
.实现该接口不需要重写任何方法,其只是作为可序列化的标志
.通过实现该接口的类需要提供一个常量SerialVersionUID,表名该类的版本,若不显示的
声明,在对象序列化时也会根据当前类的各个方面计算该类的默认SerialVersionUID
ps:但不同平台编译器实现有所不同,所以若想跨平台实现,都应显示的声明版本号.
实现存储emp的序列化和反序列化
1.使用属性name,age,gendar,salary为["张三",19,"男",5000]构造Emp类的对象
2.将第一步创建的Emp对象,序列化到文件emp.obj中
3.将第二步序列化到emp.obj中的Emp对象,反序列化处理并输出到控制台
// 实现对象的序列化
public void testOOS() throws Exception{
// 1.构建对象
Emp emp = new Emp("张三",20,"男",5000);
// 2.创建文件输出流FileOutputStream类对象,
// 使用该对象作为参数构造参数ObjectOutputStream
FileOutputStream fos = new FileOutputStream("emp.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 3.使用ObjectOutputStream的writeObject方法将Emp
// 对象写入到emp.obj文件中.
oos.writeObject(emp);
// 4.释放资源
System.out.println("序列化完毕");
oos.close();
// 生成之后emp.obj中是二进制格式,无法读懂其中内容
}
// 实现反序列化
public void testOIS() throws Exception{
FileInputStream fls = new FileInputStream("emp.obj");
ObjectInputStream ols = new ObjectInputStream(fls);
Emp emp = (Emp)ols.readObject();
System.out.println(emp);
ols.close();
}
.如果声明的类的对象序列化存到硬盘上面,之后随着需求的变化更改了类的属
性(增加了新的属性或者改名),那么当反序列化时,就会出现异常InvalClassException,这样
就会造成不兼容性的问题
但当 SerialVersionUID相同时,它就会将不一样的field以type的预设值反序列化,以避开
兼容性问题
transient关键字
对象在序列化后得到的字节序列往往比较大,有时我们在对一个对象进行序列化时,可以忽略
某些不必要的属性,从而对序列化后得到的字节序列"瘦身"
.关键字transient
.被该关键字修饰的属性在序列化时其值将被忽略
重点:
文件数据IO操作
Reader和Writer
字符流原理
.Reader是字符输入流的父类
.Writer是字符输出流的父类
.字符流是以字符(char)为单位读写,一次处理一个Unicode.
.字符流的底层仍然是基本的字节流.
常用方法
.Reader的常用方法
-int read():读取一个字符,返回的int值"低16位"有效
-int read(char[] chs):从该流中读取一个字符数组的length个字符存入该数组,返回值
为实际读取到的字符量
Writer的常用方法:
-void writer(int c):写出一个字符,写出给定int值的"低16位"表示的字符
-void writer(char[] chs):将给定字符数组中所有字符写出
-void writer(char[] chs,int offset,int len):将给定的字符数组从offset处开始连
续len个字符写出
转换流:
字符转换流原理
InputStreamReader:字符输入流
-使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并
读取
OutputStreamWriter:字符输出流
-使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流输出