天天看點

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();