• Java 序列化与反序列化


    1)Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。

    2)采用Java序列化与反序列化技术,一是可以实现数据的持久化,在MVC模式中很是有用;二是可以对象数据的远程通信。

    1、序列化是干什么的?
    简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保 存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
    2、什么情况下需要序列化
    a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
    b)当你想用套接字在网络上传送对象的时候;
    c)当你想通过RMI传输对象的时候;

    6、相关注意事项
    a)序列化时,只对对象的状态进行保存,而不管对象的方法;
    b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
    c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
    d)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了
    ,比如:
    1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
    2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。
    详细描述:
    序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io 包中的各种字节流类将其保存到文件中,管道到另一 线程中或通过网络连接将对象数据发送到另一主机。对象序列化功能非常简单、强大,在RMI、Socket、JMS、EJB都有应用。对象序列化问题在网络 编程中并不是最激动人心的课题,但却相当重要,具有许多实用意义。
    一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。
    二:java 对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用 对象序列化可以进行对象的“深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
    从上面的叙述中,我们知道了对象序列化是java编程中的必备武器,那么让我们从基础开始,好好学习一下它的机制和用法。
    java序列化比较简单,通常不需要编写保存和恢复对象状态的定制代码。实现java.io.Serializable 接口的类对象可以转换成字节流或从 字节流恢复,不需要在类中增加任何代码。只有极少数情况下才需要定制代码保存或恢复对象状态。这里要注意:不是每个类都可序列化,有些类是不能序列化的, 例如涉及线程的类与特定JVM有非常复杂的关系。
    序列化机制:
    序列化分为两大部分:序列化和反序列化。序列化是这 个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节 表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。ObjectOutputStream中的序列化过程与字节流连接,包括对象类型和版本信 息。反序列化时,JVM用头信息生成对象实例,然后将对象字节流中的数据复制到对象数据成员中。下面我们分两大部分来阐述:
    处理对象流:
    (序列化过程和反序列化过程)
    java.io包有两个序列化对象的类。ObjectOutputStream负责将对象写入字节流,ObjectInputStream从字节流重构对象。
    我们先了解ObjectOutputStream类吧。ObjectOutputStream类扩展DataOutput接口。
    writeObject() 方法是最重要的方法,用于对象序列化。如果对象包含其他对象的引用,则writeObject()方法递归序列化这些对象。每个 ObjectOutputStream维护序列化的对象引用表,防止发送同一对象的多个拷贝。(这点很重要)由于writeObject()可以序列化整 组交叉引用的对象,因此同一ObjectOutputStream实例可能不小心被请求序列化同一对象。这时,进行反引用序列化,而不是再次写入对象字节 流。
    下面,让我们从例子中来了解ObjectOutputStream这个类吧。
    // 序列化 today’s date 到一个文件中.
    FileOutputStream f = new FileOutputStream(“tmp”); //创建一个包含恢复对象(即对象进行反序列化信息)的”tmp”数据文件
    ObjectOutputStream s = new ObjectOutputStream(f);
    s.writeObject(“Today”); //写入字符串对象;
    s.writeObject(new Date()); //写入瞬态对象;
    s.flush();
    现在,让我们来了解ObjectInputStream这个类。它与ObjectOutputStream相似。它扩展DataInput接口。 ObjectInputStream中的方法镜像DataInputStream中读取Java基 本数据类型的公开方法。readObject()方法从 字节流中反序列化对象。每次调用readObject()方法都返回流中下一个Object。对象字节流并不传输类的字节码,而是包括类名及其签名。 readObject()收到对象时,JVM装入头中指定的类。如果找不到这个类,则readObject()抛出 ClassNotFoundException,如果需要传输对象数据和字节码,则可以用RMI框架。ObjectInputStream的其余方法用于 定制反序列化过程。
    例子如下:
    //从文件中反序列化 string 对象和 date 对象
    FileInputStream in = new FileInputStream(“tmp”);
    ObjectInputStream s = new ObjectInputStream(in);
    String today = (String)s.readObject(); //恢复对象;
    Date date = (Date)s.readObject();
    定制序列化过程:
    序列化通常可以自动完成,但有时可能要对这个过程进行控制。java可以将类声明为serializable,但仍可手工控制声明为static或transient的数据成员。
    例子:一个非常简单的序列化类。
    public class simpleSerializableClass implements Serializable{
    String sToday=”Today:”;
    transient Date dtToday=new Date();
    }
    序 列化时,类的所有数据成员应可序列化除了声明为transient或static的成员。将变量声明为transient告诉JVM我们会负责将变元序列 化。将数据成员声明为transient后,序列化过程就无法将其加进对象字节流中,没有从transient数据成员发送的数据。后面数据反序列化时, 要重建数据成员(因为它是类定义的一部分),但不包含任何数据,因为这个数据成员不向流中写入任何数据。记住,对象流不序列化static或 transient。我们的类要用writeObject()与readObject()方法以处理这些数据成员。使用writeObject()与 readObject()方法时,还要注意按写入的顺序读取这些数据成员。
    关于如何使用定制序列化的部分代码如下:
    //重写writeObject()方法以便处理transient的成员。
    public void writeObject(ObjectOutputStream outputStream) throws IOException{
    outputStream.defaultWriteObject();//使定制的writeObject()方法可以
    利用自动序列化中内置的逻辑。
    outputStream.writeObject(oSocket.getInetAddress());
    outputStream.writeInt(oSocket.getPort());
    }
    //重写readObject()方法以便接收transient的成员。
    private void readObject(ObjectInputStream inputStream) throws IOException,ClassNotFoundException{
    inputStream.defaultReadObject();//defaultReadObject()补充自动序列化
    InetAddress oAddress=(InetAddress)inputStream.readObject();
    int iPort =inputStream.readInt();
    oSocket = new Socket(oAddress,iPort);
    iID=getID();
    dtToday =new Date();
    }

    我的问题是在网络上传输

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
      bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
      String photodata = new String(Base64.encode(baos.toByteArray(),
        Base64.DEFAULT));

    这个变量 photodata   就可以在网络上传输

    张晓菁师姐的一个实例:

    /**@author ZXQ
     * 序列化和反序列化处理
     */
    public class SerializeUtil {
        
        public final static String CHARSET_ISO88591="ISO-8859-1";
        
        /**@author ZXQ
         * 将对象序列化
         * @param original
         * @return
         * @throws IOException
         */
        public static String serialize(Object original) throws IOException {
            if(null==original) return null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();  
            ObjectOutputStream oos = new ObjectOutputStream(baos);  
            oos.writeObject(original);  
            byte[] str = baos.toByteArray();
            oos.close();
            baos.close();
            return new String(str,CHARSET_ISO88591);
        }
        
        /**@author ZXQ
         * 反序列化
         * @param serializedstr
         * @return
         * @throws UnsupportedEncodingException
         * @throws IOException
         * @throws ClassNotFoundException
         */
        public static Object deserialize(String serializedstr) throws UnsupportedEncodingException, IOException, ClassNotFoundException{
            if(null==serializedstr)return null;
            BufferedInputStream bis=new BufferedInputStream(new ByteArrayInputStream(serializedstr.getBytes(CHARSET_ISO88591)));
            ObjectInputStream ois = new ObjectInputStream(bis);
            Object obj = ois.readObject();
            ois.close();
            bis.close();
            return obj;
        }
       

  • 相关阅读:
    HDU 5818 Joint Stacks
    HDU 5816 Hearthstone
    HDU 5812 Distance
    HDU 5807 Keep In Touch
    HDU 5798 Stabilization
    HDU 5543 Pick The Sticks
    Light OJ 1393 Crazy Calendar (尼姆博弈)
    NEFU 2016省赛演练一 I题 (模拟题)
    NEFU 2016省赛演练一 F题 (高精度加法)
    NEFU 2016省赛演练一 B题(递推)
  • 原文地址:https://www.cnblogs.com/wzyxidian/p/4383349.html
Copyright © 2020-2023  润新知