天天看点

java知识点拾遗(IO流-2)

  1. 对象流

    ObjectInputStream/ObjectOutputStream主要用于序列化(Serialization)和反序列化(Deserialization)。只有实现java.io.Serializable接口的对象才能写入流中。

  • 内存中
//写出 --> 序列化
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos =new ObjectOutputStream(new BufferedOutputStream(baos));
//操作数据类型 + 数据
oos.writeUTF("白日依山尽");
oos.writeInt(18);
oos.writeBoolean(false);
oos.writeChar('a');
//对象
oos.writeObject("黄河入海流");
oos.writeObject(new Date());
Employee emp =new Employee("马云",400);
oos.writeObject(emp);
oos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//读取 --> 反序列化
ObjectInputStream ois =new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出要保持一致
String msg = ois.readUTF(); 
int age = ois.readInt();
boolean flag = ois.readBoolean();
char ch = ois.readChar();
System.out.println(flag);
//对象的数据还原  
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = ois.readObject();

if(str instanceof String) {
  String strObj = (String) str;
  System.out.println(strObj);
}
if(date instanceof Date) {
  Date dateObj = (Date) date;
  System.out.println(dateObj);
}
if(employee instanceof Employee) {
  Employee empObj = (Employee) employee;
  System.out.println(empObj.getName()+"-->"+empObj.getSalary());
}

...
//注意一个包中只能有一个类,不论这个类是public还是默认修饰符。
//JavaBean/POJO
class Employee implements Serializable{ //Serializable接口中没有需要实现的抽象方法

  private static final long serialVersionUID = 1234567890123456789L;

  private transient String name; //transient对需要保密的属性不序列化(持久化),反序列化的结果为null。
  private int salary;

  public Employee(String name, int salary){
    this.name=name;
    this.salary=salary;
  }
}      
  • 外存中
// 写出 -->序列化
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("obj.ser")));
// 操作数据类型 +数据
oos.writeUTF("编码辛酸泪");
oos.writeInt(18);
oos.writeBoolean(false);
oos.writeChar('a');
// 对象
oos.writeObject("谁解其中味");
oos.writeObject(new Date());
Employee emp = new Employee("马云", 400);
oos.writeObject(emp);
oos.flush();
oos.close();
// 读取 -->反序列化
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("obj.ser")));
// 顺序与写出一致
String msg = ois.readUTF();
int age = ois.readInt();
boolean flag = ois.readBoolean();
char ch = ois.readChar();
System.out.println(flag);
// 对象的数据还原
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = ois.readObject();

if (str instanceof String) {
  String strObj = (String) str;
  System.out.println(strObj);
}
if (date instanceof Date) {
  Date dateObj = (Date) date;
  System.out.println(dateObj);
}
if (employee instanceof Employee) {
  Employee empObj = (Employee) employee;
  System.out.println(empObj.getName() + "-->" + empObj.getSalary());
}
ois.close();      
  • 序列化能保存的元素
  1. 只能保存对象的非静态成员变量
  2. 不能保存任何成员方法和静态成员变量
  3. 不保存transient成员变量
  4. 如果一个对象的成员变量是一个对象,这个对象的成员变量也会保存。
  5. 串行化保存的只是变量的值,对于变量的任何修饰符不能保存。
  • 使用对象流把一个对象写到文件时不仅要保证该对象是可序列化的,还要保证该对象的成员对象也是可序列化的。
  • 序列化版本不兼容
  1. 修改了类实例属性后会影响版本号,从而导致反序列化不成功。
  2. 可以为类对象指定序列化版本号serialVersionUID。
  1. 打印流
  • PrintStream
PrintStream ps=System.out;
ps.println("打印流");
ps.println(true);

ps=new PrintStream(new BufferedOutputStream(new FileOutputStream("print.txt")),true); //true 自动flush
ps.println("打印流");
ps.println(true);
ps.close();

//重定向输出
System.setOut(ps);
System.out.println("重定向到文件");

//重定向回控制台
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true);)
System.out.println("回来");      
  • PrintWriter
PrintWriter pw=new PrintWriter(new BufferedOutputStream(new FileOutputStream("print.txt")),true); //true 自动flush
pw.println("打印流");
pw.println(true);
pw.close();