zoukankan      html  css  js  c++  java
  • 输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)

    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息。 对象信息一旦写到文件上那么对象的信息就可以做到持久化了
      对象的输出流: ObjectOutputStream
      对象的输入流:  ObjectInputStream

    使用:

      对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程,对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。既然对象的输出流将对象写入到文件中称之为对象的序列化,那么可想而知对象所对应的class必须要实现Serializable接口。(查看源码可得知:Serializable接口没有任何的方法,只是作为一个标识接口存在)。

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class ObjectStreamTest {
        private static final String TMP_FILE = "box.tmp";
        
        public static void main(String[] args) {
            testWrite();
            testRead();
        }
        
        private static void testWrite() {   
            try {
                ObjectOutputStream out = new ObjectOutputStream(
                        new FileOutputStream(TMP_FILE));
                out.writeBoolean(true);
                out.writeByte((byte)65);
                out.writeChar('a');
                out.writeInt(20131015);
                out.writeFloat(3.14F);
                out.writeDouble(1.414D);
                out.writeUTF("我是字符串");
                // 写入HashMap对象
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("one", "red");
                map.put("two", "green");
                map.put("three", "blue");
                out.writeObject(map);
                // 写入自定义的Box对象,Box实现了Serializable接口
                Box box = new Box("desk", 80, 48);
                out.writeObject(box);
    
                out.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
     
        /**
         * ObjectInputStream 测试函数
         */
        private static void testRead() {
            try {
                ObjectInputStream in = new ObjectInputStream(
                        new FileInputStream(TMP_FILE));
                System.out.printf("boolean:%b
    " , in.readBoolean());
                System.out.printf("byte:%d
    " , (in.readByte()&0xff));
                System.out.printf("char:%c
    " , in.readChar());
                System.out.printf("int:%d
    " , in.readInt());
                System.out.printf("float:%f
    " , in.readFloat());
                System.out.printf("double:%f
    " , in.readDouble());
                System.out.printf("String:%s
    " , in.readUTF());
                // 读取HashMap对象
                HashMap map = (HashMap) in.readObject();
                Iterator<?> iter = map.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry)iter.next();
                    System.out.printf("%-6s -- %s
    " , entry.getKey(), entry.getValue());
                }
                // 读取Box对象,Box实现了Serializable接口
                Box box = (Box) in.readObject();
                System.out.println("box: " + box);
    
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class Box implements Serializable {
    
        private static final long serialVersionUID = 1L;
        
        private int width;   
        private int height; 
        private String name;   
    
        public Box(String name, int width, int height) {
            System.out.println("Box的构造器");
            this.name = name;
            this.width = width;
            this.height = height;
        }
    
        @Override
        public String toString() {
            return "["+name+": ("+width+", "+height+") ]";
        }
    }

    console信息:

    Box的构造器
    boolean:true
    byte:65
    char:a
    int:20131015
    float:3.140000
    double:1.414000
    String:我是字符串
    three -- blue
    two -- green
    one -- red
    box: [desk: (80, 48) ]

    最后总结一下对象输入输出流使用时需要注意:

    • 1. 如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。 Serializable接口没有任何的方法,是一个标识接口而已。

      2. 对象的反序列化创建对象的时候并不会调用到构造方法的,从console打印的信息可以看出。

    • 3. serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出的一个数字。
    • 4. 使用ObjectInputStream反序列化的时候,ObjeectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUID
    • 进行对比,如果这两个id不一致,反序列则失败。
    • 5. 如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后在序列化与反序列化的时候,jvm都不会再自己算这个 class的serialVersionUID了。
    • 6. 如果一个对象某个数据不想被序列化到硬盘上,可以使用关键字transient修饰。
    • 7. 如果一个类维护了另外一个类的引用,则另外一个类也需要实现Serializable接口。
  • 相关阅读:
    写在前面
    "路径的形式不合法"解决方案
    ExtJs学习笔记
    javascript实现ListBox左右全选、单选、多选、全请
    面向对象和面向过程的区别
    Div+CSS布局 网站设计的优点!
    libeio异步I/O库初窥
    等待进程结束
    判断Javascript变量是否为空
    后台创建进程和杀掉进程
  • 原文地址:https://www.cnblogs.com/myseries/p/10757033.html
Copyright © 2011-2022 走看看