1. 程式人生 > >(四)IO流——物件流、列印流

(四)IO流——物件流、列印流

物件流:

使用物件流之前,很明顯需要一個自定義的物件

可是普通的自定義類建立的物件並不能被物件流序列化

我們要讓這個自定義類實現一個Serializable介面(Serializable是一個標誌性介面,介面中無任何內容)

例:(省略了構造方法、get/set方法、toString方法)

public class Person implements Serializable{
    private String name;
    private int age;
}

ObjectOutputStream(物件輸出流):

物件序列化,將物件以流的形式儲存到資料夾的過程

public ObjectOutputStream(OutputStream out)                             建立指定位元組輸出流的物件輸出流物件

File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);

void  writeObject(Object  obj)                                                                儲存物件到流關聯的檔案中

File f = new File("b.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("jack",22);
oos.writeObject(p);
oos.close();

這樣就完成了物件的序列化到b.txt:

ObjectOutputStream物件輸出流輸出的物件檔案就是亂碼,只能用物件流檢視檔案內容

ObjectInputStream(物件輸入流):

物件反序列化,將檔案中物件以流的形式讀取出來的過程

public ObjectInputStream(InputStream in)                                 建立指定位元組輸入流物件的物件輸入流物件

File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);

public final Object readObject ()                                                         讀取一個物件 

File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
System.out.println(obj);                //輸出:Person{name='jack', age=22}
fis.close();

當儲存好物件後,若對類的內容作了修改,且沒有重新使用物件輸出流輸出一次關聯檔案

則readObject()方法讀取到的關聯檔案時就會出現InvalidClassException異常

因為每次修改類內容(無論是,包括修飾符、成員變數、成員方法)都會改變類中的一個serialVersionUID值

然後再次讀取該物件檔案時,就會出現序列化不同的異常

若不想因為對類內容作了一些微小修改,而導致原始檔不能被讀取的問題

可以在類中固定好serialVersionUID值,且設定為私有final靜態的!

public class Person implements Serializable{
    private String name;
    private int age;
    private static final long serialVersionUID = 12345L;        //固定serialVersionUID為任意一個值
}

若物件序列化時,部分成員變數中的資訊,不想被writeObject寫進檔案中

1.可以將成員變數設定為static靜態成員變數

這樣改成員變數就儲存在類中,建立物件時不會被物件序列化輸出到檔案中

public class Person implements Serializable{
    private String name;
    private int age1;
    private static final long serialVersionUID = 12345L;
    private static double high ;
}

弊端:設定為靜態後,反序列化該物件檔案確實不會顯示此成員變數

可是所有Person類物件的high屬性都是固定的,這樣很不靈活、很不實用

2.使用transient關鍵字

使用該關鍵字修飾的成員變數,能保證成員變數的值不被序列化到檔案中,只會短暫儲存在記憶體中

public class Person implements Serializable{
    private String name;
    private int age1;
    private static final long serialVersionUID = 12345L;
    private transient int high ;            //transient修飾了high屬性
}

做個測試:使用ObjectOutputStream輸出帶有transient關鍵字修飾的成員變數

File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("jack",20,22);        //寫入被transient關鍵字修飾的high屬性為22
oos.writeObject(p);
oos.close();

然後再用ObjectInputStream檢視該物件是否包含該成員變數的資訊

File f = new File("a.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
Person p = (Person)obj;                     //將Object物件強轉為Person物件
System.out.println(p.getHigh());            //輸出:0
fis.close();

列印流:

PrintStream類:

public PrintStream(File file)                                                          使用指定的File物件建立列印流物件

File f = new File("b.txt");
PrintStream ps = new PrintStream(f);

public PrintStream(String fileName)                                           使用指定的檔名字串建立列印流物件

PrintStream ps = new PrintStream("b.txt");

PrintStream類的print()和println()方法中可以輸出基本資料型別

其實常用System.out.println輸出語句就是一個列印流的println方法

只是建立了PrintStream物件時,指定了File物件,呼叫print方法時輸出的物件變成了文字檔案

PrintStream consolePs = System.out;            //用PrintStream物件接受系統輸出
PrintStream ps = new PrintStream("b.txt");
System.setOut(ps);                             //設定系統輸出流為ps
System.out.println("你好");                    //這個"你好" 會列印在b.txt文字內
System.setOut(consolePs);                      //設定系統輸出流為consolePs
System.out.println("你好");                    //這個"你好" 會列印在控制檯