Java IO (vii) ObjectInputStream and ObjectOutputStream

Source: Internet
Author: User
Tags object serialization

Reprint please indicate source: http://www.cnblogs.com/lighten/p/7003536.html

1. Preface

This chapter describes the important members of the Java byte Stream, object flow ObjectInputStream, and ObjectOutputStream. The previous datainputstream and DataOutputStream were just parsing and storing some of the basic data types, but more common in Java is an object instance, an object instance is very complex, how to save an object? This is what the object flow is all about. The object flow is ultimately a place of attribution, usually a file stream.

2.ObjectInputStream

ObjectInputStream Although it is necessary to accept an input source, but not inherited from FilterInputStream, which inherits from the abstract parent class InputStream, implements the ObjectInput interface, This interface implements the Datainput interface that was previously exposed, which is the basic data type. It also implements the Objectstreamconstants interface, which has only a few constants, which is a set of case-by-moment bytes when the object is converted.

It has only one constructor:

This class is very complex, first look at what the constructor has done specifically.

The first Verifysubclass () method is a security check that verifies that instances of this class or subclass can be constructed without violating security constraints, and subclasses cannot overwrite security-sensitive, non-final methods. Otherwise, the Enablesubclassimplementation serialization license will be checked.

The following three classes are the inner classes of the ObjectInputStream, which are introduced after the function.

Enableoverride determines whether to call the Readobjectoverride () or the ReadObject () method later, true when the former is called.

The Readstreamheader () method verifies the header of the read stream, and the contents of the checksum are the number of cubes and the version number.

2.1 Blockdatainputstream

There are two modes of the input stream: in the default mode, the input writes the same data as the DataOutputStream format; In block data mode, the input data is enclosed in block data tags (see object serialization specification details). Buffering depends on block Data mode: default mode, no pre-cached data; When in block data mode, all data is read in once (and buffered).

A peekinputstreamis constructed in Blockdatainputstream, which reads one byte at a time, saves it in the peekb field, and if the field >0 directly returns, If less than 0 takes a field from the wrapped stream, the Peek () method reads the bytes, which can also be read with the read () method, but only one, if you call two times in a row peek (), and then call the Read () method, the first byte is lost, which is the characteristic of this stream.

The fields are as follows:

From here you can see the cache size of the Blockdata block data, which is the default non-block mode. And we focus primarily on the True,block pattern set above.

Blockdatainputstream There are many methods, or through the inputstream of the relevant methods to see it.

The Read () method determines whether the cache is read after the end and the POS identity, and the cache is re-populated when it is read, and, when Setblockdatamode, resets the POS, end, and unread to 0 if they are not the same as the default mode (FALSE). The data is then returned to the current location, pos+1. After reading is returned-1.

The refill () method is read through a unread field and a loop of pos==end. A block of data that first reads the Blockheader data, returns the length of the block data, and assigns a value to unread. Specifically parsing block header data format process does not explain. Unread is the current data block in the flow of the remaining unread data, as long as the data is read, or countless according to the End!=0 will jump out of the loop, the next unread may still not be 0, that is, the current data block has not been read, reading is 0, and back to the resolution block header data process.

Currentblockremaining () returns data that is not read by the current block, including the unread data in the cache and the remaining chunk data that is not read in the stream.

  Blockdatainputstream Summary : see here, Blockdatainputstream other methods also did not see the need, it should be simple. The main function of this class is to parse the data stream by block, a data block includes the size and the body, there are some signs and the length of the body in the block. Each read is a block of data read one by one, not guaranteed to read a data block. The size of each block is 1024 bytes. Look at the Java specification, which is designed primarily for the pre-and post-compatibility of object serialization, where storing and reading in blocks is compatible with the 1.1 minor version prior to version 1.2 and the extension after 1.2.

2.2HandleTable

This class is a non-synchronized table used to track the handle of an object's association. During deserialization, an object is first assigned a handle by calling the Assign method. This method allows the allocated handle to be open, depending on the exception state of other handles, can be registered through the Markdependency method, or an exception can be directly associated by calling Markexception. When the handle is marked as an exception, Handletable assumes responsibility for propagating the exception to other objects that depend on the tagged object. The above is part of the JDK on the comments, may not be translated into place, and then look at the source:

According to the above explanation and then look at the source code, here are three arrays is very clear, one is the state of the handler object, a storage object or exception, a memory of all dependent on this object handler. Handlerlist This class is simple, is a record object dependent handle ordinal array, add (int handler) method is added. The methods in Handlertable are as follows:

Clear (): Resetting the array to Null,byte is the 0;size () method is to return; the Grow () method is to enlarge the array and copy the original data. The main focus is on the three methods mentioned earlier:

An object is first marked in an unknown state and stored in the entries.

Depending on the state of the choice, from the point of view of the annotation, an object is assign to adjust the other methods, this time the state of the unknow. The goal is the normal situation, the dependency also does not have to change, the target has the anomaly, according to the dissemination principle, wants to propagate the target anomaly to this object. If the target is also unknown, a list will be set up for the target and then judged and conducted later.

The Markexception method is also clear, that is, the anomaly of the target is transmitted to its dependence, as well as dependence. Finish () is determined after the end of the unknown state of the change to OK state, so before judging the abnormal state of break, because the processing is done, and OK state will throw an exception, because this state should be the last to be determined.

  handlertable Summary : The composition of the object may be very complex, in the process of deserialization, if there is an error, should be transmitted to all dependencies, such as a object has a b,b in the C deserialization failed, B is certainly abnormal, a nature is also abnormal. The handlertable is used to calculate the abnormal conduction.

2.3ValidationList

Once the object graph is deserialized, a prioritized list of callbacks is executed.

Register obj with validationlist, with precedence, to insert the associated position of the linked list. Callback is a structure that can form a chain structure with the next pointer.

The callback will be executed in the final order.

2.4 ReadObject ()

Using object flow is, of course, to read bytes into an object, and not care about some basic reading methods, of course, these methods are very simple, are used before the blockdatainputstream of the relevant methods, see before the understanding is not difficult.

This is not a subclass, Enableoverride is false. So what we need to focus on is the process behind it. Initially, Passhandle is-1, that is, Outerhandle is-1. It is also easier to understand the logic before handlertable, that is, if the query throws with an exception, no callback is executed, and obj is returned. Finally, reset the Passhandle to the original value. See below what ReadObject0 (false) has done.

The beginning of this paragraph is compatible with the old model, without the need to see.

Resets the handle by reading the reset character.

This is based on the tag, using a different way to parse. The inside is more complex, no longer detailed introduction.

2.5 Summary Read Process

Does not consider the old version (1.1 times to version) of the read, that is, non-block mode. Reading an object stream, the first read of the four bytes is constant, the number of Rubik's Cube [-84,-19], and the version number [0,5],short type. This read is already starting to read a block of 1024 bytes. The 5th byte is the switch option for the READOBJECT0 () above.

3.ObjectOutputStream

Slightly, reverse step (look very tired-.) -!)。 The reverse process is mainly the WriteObject method.

4. PostScript

In this paper, ObjectInputStream is described in detail, but there are some unclear, The individual has doubts about the handler.markdependency in the ReadObject method, since the initial passhandle should be 1, which should be useless. The eclipse breakpoint cannot see the value of the variable here and is difficult to verify. ObjectInputStream roughly also on these content, just a split analysis of a bit. WriteObject did not carry on the introduction, certainly is the corresponding content with the ReadObject. Here is a small example.

public class Student implements serializable{/** * */private Static final Long serialversionuid = 4484961141733473265l;private int id;private String name;private int age;public Studen t (int ID, String name, int age) {this.id = Id;this.name = Name;this.age = age;} public int getId () {return ID;} public void setId (int id) {this.id = ID;} Public String GetName () {return name;} public void SetName (String name) {this.name = name;} public int getage () {return age;} public void Setage (int.) {this.age = age;} @Overridepublic String toString () {return "Student [id=" + ID + ", name=" + name + ", age=" + Age + "]";}} 
public class Teacher implements serializable{/** * */private Static final Long serialversionuid = -312001656457242689l;private int age;private String name;private Student student;pub LIC Teacher (int age, String name, Student Student) {this.age = Age;this.name = Name;this.student = Student;} public int getage () {return age;} public void Setage (int.) {this.age = age;} Public String GetName () {return name;} public void SetName (String name) {this.name = name;} Public Student getstudent () {return Student;} public void Setstudent (Student Student) {this.student = Student;} @Overridepublic String toString () {return "Teacher [age=" + Age + ", name=" + name + ", student=" + student + "]";}} 
    @Testpublic void Test () throws IOException {Student Student = new Student (10, "Zhang San", 12); Teacher Teacher = new Teacher (32, "John Doe", student); Bytearrayoutputstream BAOs = new Bytearrayoutputstream () objectoutputstream oos = new ObjectOutputStream (BAOs); o Os.writeobject (teacher); byte[] obj = Baos.tobytearray (); System.out.println (obj.length); System.out.println (arrays.tostring (obj)); Bytearrayinputstream Bais = new Bytearrayinputstream (obj); ObjectInputStream ois = new ObjectInputStream (Bais); try { Teacher t = (Teacher) ois.readobject (); System.out.println (t);} catch (ClassNotFoundException e) {e.printstacktrace ();}}

The objects that need to be serialized must implement the Serializable interface, or the Externalizable interface. This also gives an example:

public class Classroom implements Externalizable {private Teacher teacher;private list<student> students; @Overridepublic void Writeexternal (ObjectOutput out) throws IOException {out.writeobject (teacher); Out.writeobject (students);} @SuppressWarnings ("unchecked") @Overridepublic void Readexternal (ObjectInput in) throws IOException, classnotfoundexception {this.teacher = (teacher) in.readobject (); this.students = (list<student>) in.readObject ( );} Public Teacher Getteacher () {return Teacher;} public void Setteacher (Teacher Teacher) {this.teacher = Teacher;} Public list<student> getstudents () {return students;} public void Setstudents (list<student> students) {this.students = students;} @Overridepublic String toString () {return "classroom [teacher=" + Teacher + ", students=" + students + "]";}} 
    @Testpublic void Test2 () throws IOException {Student Student = new Student (10, "Zhang San", 12); Teacher Teacher = new Teacher (32, "John Doe", student); Classroom classroom = new Classroom (); list<student> students = new arraylist<student> (); Students.add (Student); Classroom.setstudents (students ); Classroom.setteacher (teacher); Bytearrayoutputstream BAOs = new Bytearrayoutputstream () objectoutputstream oos = new ObjectOutputStream (BAOs); o Os.writeobject (classroom); byte[] obj = Baos.tobytearray (); System.out.println (obj.length); System.out.println (arrays.tostring (obj)); Bytearrayinputstream Bais = new Bytearrayinputstream (obj); ObjectInputStream ois = new ObjectInputStream (Bais); try { Classroom C = (classroom) ois.readobject (); System.out.println (c);} catch (ClassNotFoundException e) {e.printstacktrace ();}}

Some of this article is not clear, perhaps some mistakes, if found out please point out. The following two articles can also be consulted.

Objectstreamfield and objectstreamclass:http://blog.csdn.net/silentbalanceyh/article/details/8250096

Objectiuputstream and objectoutputstream:http://blog.csdn.net/silentbalanceyh/article/details/8294269

5. Supplementary 5.1 Object stream write file can only write one object problem

Do not write to the file first, write an array to see the phenomenon:

    @Testpublic void Test3 () throws IOException {Student Student = new Student (10, "Zhang San", 12); Teacher Teacher = new Teacher (32, "John Doe", student); Bytearrayoutputstream BAOs = new Bytearrayoutputstream () objectoutputstream oos = new ObjectOutputStream (BAOs); o Os.writeobject (student); Oos.writeobject (teacher); byte[] obj = Baos.tobytearray (); System.out.println (obj.length); System.out.println (arrays.tostring (obj)); Bytearrayinputstream Bais = new Bytearrayinputstream (obj); ObjectInputStream ois = new ObjectInputStream (Bais); try { Student s = (Student) ois.readobject (); System.out.println (s); Teacher t = (Teacher) ois.readobject (); System.out.println (t);} catch (ClassNotFoundException e) {e.printstacktrace ();}}

Here write two objects, actually experimented two times, the first time only wrote a student object, the second write the student and teacher objects, compared bytecode, the front student exactly the same. The difference is as follows:

115 when another call to ReadObject is an identifier, it means that an object is read. The above write two objects through the ByteArray stream is no problem, do the following:

Then experiment with it. Writes two objects to the file, then reads.

    @Testpublic void Test4 () throws IOException {String path = ObjectStreamTest.class.getClassLoader (). GetResource (""). GetPath () + "Objectstream.txt";//system.out.println (path); File File = new file (path); Student Student = new Student (10, "Zhang San", 12); Teacher Teacher = new Teacher (32, "John Doe", student); FileOutputStream fos = new FileOutputStream (file), ObjectOutputStream oos = new ObjectOutputStream (FOS); oos.writeobject (student); Oos.writeobject (teacher); Oos.flush (); Oos.close (); FileInputStream fis = new FileInputStream (new File), @SuppressWarnings ("resource") objectinputstream ois = new ObjectInputStream (FIS); try {Student s = (Student) ois.readobject (); System.out.println (s); Teacher t = (Teacher) ois.readobject (); System.out.println (t);} catch (ClassNotFoundException e) {e.printstacktrace ();}}

The experimental results are as follows:

There is no problem, the experimental environment is JDK8, may be in this version to solve the problem, perhaps due to other problems caused. All in all, there is no test problem. All the test programs have forgotten to turn off the input and output stream, you have to make up your readers, lazy changes.

Java IO (vii) ObjectInputStream and ObjectOutputStream

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.