最近在看设计模式,上面介绍到装饰模式时引用到了IO类库作为例子,想写一个简略的总结
在java中,io基本上分为字节流和字符流两大类,字节流以InputStream和OutputStream为顶层类结构
InputStream (abstract) FileInputStream FileterInoutStream BufferedInputStream (支持mark/reset) DataInputStream (有自动读入基本类型数据的方法) PushbackInputStream(不支持mark/reset) ObjectInputStream ByteArrayInputStream 复制代码
inputStream
该类是一个抽象类,是字节输入流的超类,此类中包括了文件操作的一些基本方法
available()
返回可读取的字节数,此方法在改类中总是返回0复制代码
mark/reset()
标记与返回 另外有mark方法设置最大读取字节,超过字节数就回来了。本类中依旧不能使用复制代码
read
该类中共有三各read方法,无参,一个字节数组,以及字节数组加上规定的读入地址和读入长度。读取出的字节会覆盖原来有的数据(如果该位有的话)复制代码
FileInputStream
在java api中 对该类定义为:从文件系统中读取字节流。如音频,图像之类的字节流数据用该类读取。
FileterInoutStream
此类作为装饰类的父类,包含一个基本输入流,为数据的读取提供一些额外的功能,这些功能应该在其子类实现
DataInputStream
该类扩展了父类的方法,主要用于读取java基本类型数据
ObjectInputStream
该类主要实现类读取java对象的功能,最主要的用途在于对象的序列化与放序列化。
注意,实现序列化需要实现serializable 接口,该接口可以继承,当子类与父类都实现serializable接口
public class User implements Serializable{ public int i=10; public String name="zhaosi"; public User() { System.out.println("user constructor"); } public User(String name){ this.name=name; }}复制代码public class Person extends User{ static int sb=10; int b=11; public Monkey m =new Monkey(); public Person() { } public void say(){ System.out.println(b); }}复制代码public class ObjectStream { public static void main(String[] args) { ObjectOutputStream oo = null; ObjectInputStream oi = null; try { oo = new ObjectOutputStream(new FileOutputStream(new File("./object.txt"))); oi = new ObjectInputStream(new FileInputStream(new File("./object.txt"))); Person p = new Person(); p.name="wangwu"; oo.writeObject(p); Person pp = (Person) oi.readObject(); System.out.println(pp.name); }catch(Exception e){ } finally { try { oo.close(); oi.close(); } catch (Exception e2) {}}}}复制代码···
public class Monkey implements Serializable { public Monkey() { System.out.println("monley constructor"); } public int i=20; public void sys(){ System.out.println("monley"); } public String toString(){ return "Monkey"; }}···
结果
user constructor monley constructor wangwu 即如果与要持久化关联的对象都实现serilized接口的话,存入该对象时一同存入与其关联的对象当父类未持久化时
修改上述文件 将user类 serializable 接口去除,person 实现serializable接口
运行结果 user constructor monley constructor user constructor zhaosi复制代码
java api 中有此解释:
对于没有实现 java.io.Serializable 接口的任何对象,序列化不会对其字段进行读取或赋值。非 serializable 的 Object 的子类可以为 serializable。在此情况下,非 serializable 类必须具有无参数的构造方法以允许其字段能被初始化。在此情况下,子类负责保存和恢复非 serializable 类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用于恢复状态的 get 和 set 方法
我理解的大致意思为,当父类未实现Serializable接口,该对象不会序列化,当子类反序列化取出来时候,子类重新创建一个父类对象,原来对与父类相关的改变丢失。
当内部成员Mokey未实现Serializable
去除Mokey类Serializable 接口 结果 user constructormonley constructorperson constructorjava.io.NotSerializableException: TestIO.Monkey进程终止
PushbackInputStream
此类可支持回退操作,其构造参数传入一个缓冲区,当缓冲区为空时,读操作调用底层的read方法,如果缓冲区不为空,则先读取缓冲区
public class PushbackInputStreamTest { public static void main(String[] args) { PushbackInputStream ps =null; ByteArrayInputStream bs=null; String str ="haha,nihao"; try { bs= new ByteArrayInputStream(str.getBytes()); ps = new PushbackInputStream(bs); int temp =0; while((temp=ps.read())!=-1){ if(temp == ','){ ps.unread(temp); temp=ps.read(); System.out.println("(回退"+(char)temp+")"); }else{ System.out.println((char)temp); } } }catch(Exception e){ e.getMessage(); } }}复制代码
PushbackInputStream ,ByteArrayInputStream 不用关闭