当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。