當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Java ObjectInputStream和ObjectOutputStream的區別用法及代碼示例


在軟件項目中,很多情況下都需要傳輸數據,可以使用Java IO包中的ObjectOutputStream ObjectInputStream來處理。通常,數據以二進製格式寫入,因此我們無法查看其內容。 Serialization是將對象寫入輸出流的過程。我們可以編寫一個類對象本身,它包含原始數據類型和 Java 對象圖的組合。反序列化是從輸入流重建對象的過程。

執行:讓我們看看ObjectOutputStream 圖中所示為我們創建的POJO類稱為“VehicleSpecifications”。

Note: It should implement Serializable, otherwise, java.io.NotSerializableException will be thrown.

示例 1:

Java


// Java Program simply illustrating POJO / Model class
// Importing input output class 
import java.io.Serializable;
// Class 1
// Implements Serializable  for POJO class to avoid
// NotSerializableException will be thrown
public class VehicleSpecifications implements Serializable {
    // Member variables of this class
    private String color;
    private String type;
    private String name;
    private double price;
    // Constructors of this class
    // Constructor- 1
    // Default constructor
    public VehicleSpecifications() {}
    // Constructor- 2
    // Parameterized constructor accepting all attributes and
    // helps to create a VehicleSpecifications class
    public VehicleSpecifications(String color, String type,
                                 String name, double price)
    {
        // This keyword refers to current object itself
        this.color = color;
        this.type = type;
        this.name = name;
        this.price = price;
    }
    // Methods of this class
    // Specifically  Getter and Setter methods
    // Method 1
    public double getPrice() { return price; }
    // Method 2
    public void setPrice(double price)
    {
        this.price = price;
    }
    // Method 3
    public String getName() { return name; }
    // Method 4
    public void setName(String name) { this.name = name; }
    // Method 5
    public String getColor() { return color; }
    // Method 6
    public void setColor(final String color)
    {
        this.color = color;
    }
    // Method 7
    public String getType() { return type; }
    // Method 8
    public void setType(final String type)
    {
        this.type = type;
    }
}


No output is as till now by far we have implemented just the constructors and defined body of methods including getters and setters. 

Now let us create a few vehicle specifications and write them in a file. As VehicleSpecifications implemented Serializable functionality, the data can be written to a file in a binary format. For this we will be using “writeObject” function and by using that we can write class attributes using write methods provided by ObjectOutputStream.

示例 2:

Java


// Class 2
// Java Program to Create Few VehicleSpecification and
// Writing in a File
// Importing required classes from packages
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
// Main class
public class VehicleSpecificationsSerializer {
    // main driver method
    public static void main(String[] args)
    {
        // Output file been passed in a string
        String sampleOutputFile = "VehicleSpecification.db";
        // Try block to check for exceptions
        try {
            // Create a objectoutputstream accepting the
            // file name as VehicleSpecification.db
            ObjectOutputStream vehicleObjectOutput
                = new ObjectOutputStream(
                    new FileOutputStream(sampleOutputFile));
            // Create a list of VehicleSpecifications class
            List<VehicleSpecifications> listSpecifications
                = new ArrayList<VehicleSpecifications>();
            // Add the necessary data using standard add()
            // method Custom input
            listSpecifications.add(
                new VehicleSpecifications("Radiant Red",
                                          "SUV", "WR-V",
                                          1700000f));
            listSpecifications.add(
                new VehicleSpecifications("Metallic Blue",
                                          "SUV", "WR-V",
                                          1800000f));
            listSpecifications.add(
                new VehicleSpecifications(
                    "Black", "SUV", "WR-V", 1900000f));
            // We are writing the whole object into the file
            // which is a list item of VehicleSpecifications
            // object
            vehicleObjectOutput.writeObject(
                listSpecifications);
            // Closing the connection to release memory
            vehicleObjectOutput.close();
        }
        // Catch block to handle the exceptions
        catch (IOException ex) {
            // Print the exceptions along with line number
            // using printStackTrace() method
            ex.printStackTrace();
        }
    }
}


注意:執行上述代碼時,我們可以看到數據是以二進製格式寫入的,這意味著它隻是一種不可讀的格式。

因此,為了以可讀格式獲取數據,我們使用ObjectInputStream,並且由於我們必須檢索類對象數據(即VehicleSpecifications數據),因此我們需要使用readObject()方法,該方法可以讀取類屬性使用ObjectInputStream提供的read()方法。

示例 3:

Java


// Java Program to make above code human-readable
// Importing classes from required packages
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
// Main class
public class VehicleSpecificationsDeSerializer {
    // main driver method
    public static void main(String[] args)
    {
        // Input file
        String sampleInputFile = "VehicleSpecification.db";
        // Try block to check for exceptions
        try {
            // Creating an object of ObjectInputStream class
            ObjectInputStream vehicleObjectInputStream
                = new ObjectInputStream(
                    new FileInputStream(sampleInputFile));
            // Creating a List class object
            // Declaring object of user defined type
            // (VehicleSpecifications)
            List<VehicleSpecifications>
                vehicleSpecificationsListData
                = new ArrayList<VehicleSpecifications>();
            // Using readObject, bringing back the whole
            // list item of VehicleSpecifications into scope
            // readObject which can read class attributes
            // using read methods provided by
            // ObjectInputStream.
            vehicleSpecificationsListData
                = (ArrayList<VehicleSpecifications>)
                      vehicleObjectInputStream.readObject();
            // Iterating over above object created
            for (int i = 0;
                 i < vehicleSpecificationsListData.size();
                 i++) {
                VehicleSpecifications vehicleSpecifications
                    = vehicleSpecificationsListData.get(i);
                // Print and display commands
                System.out.println(
                    "Color .."
                    + vehicleSpecifications.getColor());
                System.out.println(
                    "Name .."
                    + vehicleSpecifications.getName());
                System.out.println(
                    "Price .."
                    + vehicleSpecifications.getPrice());
                System.out.println(
                    "Type .."
                    + vehicleSpecifications.getType());
            }
            // Closing the resources to free up memory space
            vehicleObjectInputStream.close();
        }
        // Catch block to handle the exceptions
        // Catch block 1
        // Handling input output  exceptions
        catch (IOException ex) {
            // Printing the line number where exception
            // occurred using printStackTrace() method
            ex.printStackTrace();
        }
        // Catch block 2
        // Handle exception if class not found
        catch (ClassNotFoundException e) {
            // Again, printing the line number where
            // exception occurred using printStackTrace()
            // method
            e.printStackTrace();
        }
    }
}


輸出:

輸出說明:

因此,我們看到的是人類可讀格式的輸出。因此,我們的整個類對象集可以使用 java.io 包提供的 ObjectInput 和 ObjectOutput 流進行移植。因此,現在讓我們在了解ObjectOutputStream 和ObjectInputStream 的內部工作流程後,最終討論它們之間的差異。它們以表格格式顯示如下:

ObjectOutputStream ObjectInputStream
寫入 Java 對象 讀取 Java 對象
使用ArrayList,我們可以編寫多個Java對象 通過ArrayList,我們可以讀取和檢索多個Java對象
默認情況下,ArrayList是可序列化的,因此如果我們編寫像String這樣的對象ArrayList,則不需要實現可序列化,但元素應該是可序列化的。 writeObject()用於寫入ArrayList數據 ArrayList對象反序列化時,使用readObject()讀取ArrayList數據
如果我們使用類對象(如上麵討論的示例),該類應該實現可序列化,然後隻有在使用 writeObject() 方法時,才不會拋出 java.io.NotSerializedException 我們需要在使用readObject()時轉換相同格式的對象
writeObject()方法以二進製格式寫入序列化數據 readObject()方法反序列化並讀取數據
二進製格式不可讀。盡管我們傳遞的是 String、double 等原始數據,但在寫入時,數據是以二進製格式存儲的。 為了獲得完美的類格式的數據,我們需要使用ObjectInputStream來反序列化數據,我們可以獲得寫入的所有原始數據
作為一個完整的對象,它正在被寫入,隻要對象被序列化並以正確的格式寫入,就不會丟失數據 同樣,讀取整個對象,不會丟失數據,並且我們也可以輕鬆迭代數據。

不僅通過 writeObject() 寫入類對象,它還支持其他寫入方法,如下所示,以及為每種數據類型寫入的更多方法。

write(byte[] buffer)-> 寫入字節數組。

writeBoolean(布爾值) -> 寫入布爾值

writeDouble(double value)-> 寫入 64 位 double 值

writeInt(int value)-> 寫入 32 位 int

不僅通過readObject()讀取類對象,它還支持如下所示的其他讀取方法以及更多讀取每種數據類型的方法。

read()-> 讀取數據字節

readBoolean() -> 讀取布爾值。

readDouble()-> 讀取 64 位雙精度值。

readInt()->讀取 32 位 int。

ObjectOutputStream 可能的例外情況如下:

IOException - 如果在寫入流頭期間發生任何 I/O 錯誤

安全異常

NullPointerException - 如果 OutputStream 未初始化,因此它可能為 null

ObjectInputStream 可能的例外情況如下:

StreamCorruptedException - 不正確的流標頭

IOException - 如果讀取流標頭時發生任何 I/O 錯誤

安全異常

NullPointerException - 如果輸入流未初始化,因此它可能為空

writeObject 可能出現的異常如下:

InvalidClassException - 類的序列化應該正確,如果有問題。

NotSerializableException - 某些要序列化的對象未實現 java.io.Serializable 接口。這種情況很常見,因此必須讓類實現 Serialized

IOException - 在寫入期間,如果底層 OutputStream 發生 IO 錯誤。

readObject 可能出現的異常如下:

InvalidClassException - 類的序列化應該正確,如果有問題。

ClassNotFoundException - 序列化對象的類應該可用,如果找不到的話。

IOException - 讀取期間,如果底層 InputStream 發生 IO 錯誤

流損壞異常

可選數據異常



相關用法


注:本文由純淨天空篩選整理自priyarajtt大神的英文原創作品 Difference Between ObjectInputStream and ObjectOutputStream in Java。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。