在軟件項目中,很多情況下都需要傳輸數據,可以使用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 錯誤 流損壞異常 可選數據異常 |
相關用法
- Java ObjectInputStream readChar()用法及代碼示例
- Java ObjectInputStream readDouble()用法及代碼示例
- Java ObjectInputStream readField()用法及代碼示例
- Java ObjectInputStream readFloat()用法及代碼示例
- Java ObjectInputStream readFully()用法及代碼示例
- Java ObjectInputStream readInt()用法及代碼示例
- Java ObjectInputStream readLine()用法及代碼示例
- Java ObjectInputStream readLong()用法及代碼示例
- Java ObjectInputStream readObject()用法及代碼示例
- Java ObjectInputStream readObjectOverride()用法及代碼示例
- Java ObjectInputStream readShort()用法及代碼示例
- Java ObjectInputStream readStreamHeader()用法及代碼示例
- Java ObjectInputStream readUTF()用法及代碼示例
- Java ObjectInputStream readUnshared()用法及代碼示例
- Java ObjectInputStream readUnsingedByte()用法及代碼示例
- Java ObjectInputStream registerValidation()用法及代碼示例
- Java ObjectInputStream readFields()用法及代碼示例
- Java ObjectInputStream readUnsignedByte()用法及代碼示例
- Java ObjectInputStream readUnsignedShort()用法及代碼示例
- Java ObjectInputStream resolveClass()用法及代碼示例
- Java ObjectInputStream skipBytes()用法及代碼示例
- Java ObjectInputStream available()用法及代碼示例
- Java ObjectInputStream close()用法及代碼示例
- Java ObjectInputStream read()用法及代碼示例
- Java ObjectInputStream readBoolean()用法及代碼示例
注:本文由純淨天空篩選整理自priyarajtt大神的英文原創作品 Difference Between ObjectInputStream and ObjectOutputStream in Java。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。