標籤:java-io java流 流操作 stream io
Serializable序列化
1 對象的序列化
class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { return "Name:" + this.name + ", Age:" + this.age; } } public class serialTest { public static void main(String[] args) { String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt"; Person p1 = new Person("zhangsan",12); Person p2 = new Person("lisi",14); //此處建立檔案寫入流的引用是要給ObjectOutputStream的建構函式玩兒 FileOutputStream fos = null; ObjectOutputStream oos = null; try { fos = new FileOutputStream(path); oos = new ObjectOutputStream(fos); //這裡可以寫入對象,也可以寫入其他類型資料 oos.writeObject(p1); oos.writeObject(p2); } catch (IOException e) { e.printStackTrace(); } finally { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
結果:
2 還原序列化
package com.yin.serialize;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class serialTestFan { public static void main(String[] args) { String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt"; //好吧,這裡代碼寫得著實有點長了,還要拋異常什麼的 //如果你也看的煩,那就在主方法上拋吧,構造方法裡用匿名對象就好了 //什嗎?別告訴我你不知道匿名對象 FileInputStream fis = null; ObjectInputStream ois = null; try { fis = new FileInputStream(path); ois = new ObjectInputStream(fis); //這裡返回的其實是一個Object類對象 //因為我們已知它是個Person類對象 //所以,就地把它給向下轉型了 Person p = (Person)ois.readObject(); System.out.println(p); Person p2 = (Person)ois.readObject(); System.out.println(p2);// Person p3 = (Person)ois.readObject();// if (p3 == null) {// System.out.print("p3==null");// }else {// System.out.println(p3);// } //拋死你,煩煩煩~!!! } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { //還是要記得關閉下流 ois.close(); } catch (IOException e) { e.printStackTrace(); } } }}
結果:
對應於上面序列化時寫入的對象。
值得注意的是,如果把注釋的代碼去掉注釋,則出現EOFException異常,也就是說讀取完資料對象之後,不允許往下讀取了。只能有多少對象資料讀取多少對象。
3 管道流
線程的通訊
package com.yin.serialize;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;//實現Runnable介面,實現一個讀的線程class Read implements Runnable { private PipedInputStream in; //將需要讀的管道流傳入到建構函式中 public Read(PipedInputStream in) { this.in = in; } //實現讀這一線程 public void run() { try { byte[] buf = new byte[1024]; int temp = 0; //迴圈讀取 //read是一個阻塞方法,需要拋異常 //此處把列印流的代碼也加入進來 //是因為如果沒有讀取到資料,那麼列印的代碼也無效 while((temp = in.read(buf)) != -1) { String str = new String(buf,0,temp); System.out.println(str); } } catch (IOException e) { //其實這裡應拋出一個自訂異常的 //暫時我還沒弄清楚 e.printStackTrace(); } finally { try { //我已經拋火了,這隻是為了提醒自己異常很重要 in.close(); } catch (IOException e) { e.printStackTrace(); } } } }//這裡實現一個寫的類class Write implements Runnable { private PipedOutputStream out; //將管道輸入資料流傳進來 public Write(PipedOutputStream out) { this.out = out; } public void run() { try { //這裡開始寫出資料 out.write("管道操作=========看到沒,就是這句!!".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { //其實應該可以把這個關閉方法寫到上面那個try裡邊 //但是這樣感覺怪怪的,邏輯不大對 out.close(); } catch (IOException e) { e.printStackTrace(); } } }}public class Demo { public static void main(String[] args) { PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); try { //串連管道 in.connect(out); //建立對象,開啟線程 //此處同樣放進try...catch裡面 //因為如果沒有連結管道,下面操作無意義 Read r = new Read(in); Write w = new Write(out); //把已經實現好run方法的對象放入線程中執行 new Thread(r).start(); new Thread(w).start(); } catch (IOException e) { e.printStackTrace(); } }}
結果:
我們知道,位元組流和字元流都需要數組來進行流的中轉
而管道流則直接串聯兩條流,一邊發送資料,一邊接收
然而,同時通訊的的兩種狀態,如何才能確定發送和接收的一致性呢
那麼,就需要用到線程,無論是接收方還是發送方先執行
總會造成一個線程的阻塞狀態,從而等待另一方的資料傳過來
總體而言,管道流的目的,也就是為了線程通訊
此外,還有PipedReader和PipedWriter類,操作原理都一樣
4 DataOutputStream和DataInputStream類
基礎資料型別 (Elementary Data Type)的寫入
package com.yin.serialize;import java.io.DataOutputStream;import java.io.FileOutputStream;import java.io.IOException;public class DataStreamTest { public static void main(String[] args) { String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt"; DataOutputStream d = null; try { //此處需要傳入一個OutputStream類的對象 d = new DataOutputStream(new FileOutputStream(path)); //開始寫入基礎資料型別 (Elementary Data Type) d.writeInt(12); d.writeBoolean(true); d.writeDouble(12.2223); d.writeChar(97); //重新整理流 d.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { d.close(); } catch (IOException e) { e.printStackTrace(); } } }}
結果:
5 基礎資料型別 (Elementary Data Type)的讀取
import java.io.DataInputStream;import java.io.FileInputStream;import java.io.IOException;public class DataReadTest { public static void main(String[] args) { String path = "D:\\Program Files (x86)\\ADT\\workspace\\JavaIO\\demoTest.txt"; DataInputStream d = null; try { d = new DataInputStream(new FileInputStream(path)); //按儲存順序讀取基礎資料型別 (Elementary Data Type) System.out.println(d.readInt()); System.out.println(d.readBoolean()); System.out.println(d.readDouble()); System.out.println(d.readChar()); } catch (IOException e) { e.printStackTrace(); } finally { try { d.close(); } catch (IOException e) { e.printStackTrace(); } } }}
結果:
這個結果與上面的資料寫入順序一致。也就是說讀取資料和寫入資料一致!!注意!否則會發生資料的列印錯誤!
參考 :http://www.cnblogs.com/nerxious/archive/2012/12/17/2822365.html
源碼下載
Java IO流詳解(四)