什么是Java序列化,如何实现序列化

1 序列化概念

  • 序列化就是一个把Java对象编码成一串二进制的过程
    • 序列化的用途:可以将对象放入文件存储、或者放入网络传输
  • 反序列化就是一个解码的过程
  • 序列化没有固定的标准,有各种各样序列化的方法

Java自带序列化接口

  • 创建一个User类
  • 在main方法里创建User对象,通过ObjectOutputStream把对象写入到文件中
    • 编译报错
    • 因为该对象不能被序列化
  • 让User类实现 Serializable 接口
  • 把User对象写入到文件成功!
  • 我们发现写入后的文件大小比对象所有的属性值大很多
    • 因为java的Serializable会把类的继承体系也写到文件里,多了很多额外的信息
    • 会变得更臃肿,不利于大数据的数据在分布式系统中传输

    [Java] 纯文本查看 复制代码

    ?

    1

    2

    3

    4

    5

    6

    7

    private static void encoding() throws Exception {

        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("E:/test/obj1.txt"));

        SerializableUser user = new SerializableUser();

        user.set("9521", "周星星", 23, 10000D);

        os.writeObject(user);

        os.close();

    }

  • [Java] 纯文本查看 复制代码

    ?

    1

    2

    3

    4

    5

    6

    7

    private static void decoding() throws Exception {

        ObjectInputStream oi = new ObjectInputStream(new FileInputStream("E:/test/obj1.txt"));

        Object object = oi.readObject();

        SerializableUser user = (SerializableUser) object;

        System.out.println(user);

        oi.close();

    }

自定义序列化(FileOutputStream)

  • 我们通过把对象的属性拼接成字符串
  • 通过 FileOutputStream 将字符串写入文件中
  • 写入后发现文件大小变小了很多(由150字节 --> 50字节)
    • 因为所有的属性都变成字符串格式,没有额外的信息
  • 反序列化的时候读取一行数据自己切割后放入对象
  • 存在一个问题,如果是一个Int类型的值,它变成字符串后字节长度变长了

将对象转成 json 格式再序列化

  • 通过把对象转成 json 格式序列化后可以很方便的对数据进行操作

[Java] 纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

private static void encoding2() throws Exception {

    SerializableUser user = new SerializableUser();

    user.set("9521", "周星星", 23, 10000D);

    Gson gson = new Gson();

    String json = gson.toJson(user);

    System.out.println(json);

    FileOutputStream fos = new FileOutputStream("E:/test/obj2.txt");

    fos.write(json.getBytes("utf-8"));

    fos.flush();

    fos.close();

}

[Java] 纯文本查看 复制代码

?

1

2

3

4

5

6

7

8

private static void decoding2() throws Exception {

    BufferedReader br = new BufferedReader(new InputStreamReader((new FileInputStream("E:/test/obj2.txt"))));

    String json = br.readLine();

    br.close();

    Gson gson = new Gson();

    SerializableUser user = gson.fromJson(json, SerializableUser.class);

    System.out.println(user);

}


通过 DataOutputStream 优化上述代码

  • 将对象中的每一个属性按照它原来的类型进行逐个编码
    • 可以对基本数据类型按类型机制编解码
  • 我们通过 DataOutputStream 把属性一个一个写入到文件
  • 发现通过这种方式序列化后文件更加小了(再由50字节 --> 29字节)
  • 字符串在原来长度上多2个字符,用于表示字符串的边界

[Java] 纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

private static void encoding3() throws Exception {

    SerializableUser user = new SerializableUser();

    user.set("9521", "周星星", 23, 10000D);

     

    DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:/test/obj3.txt"));

    dos.writeUTF(user.getId());

    dos.writeUTF(user.getName());

    dos.writeInt(user.getAge());

    dos.writeDouble(user.getSalary());

     

    dos.flush();

    dos.close();

}

[Java] 纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

private static void decoding3() throws Exception {

    SerializableUser user = new SerializableUser();

     

    DataInputStream dis = new DataInputStream(new FileInputStream("E:/test/obj3.txt"));

    String id = dis.readUTF();

    String name = dis.readUTF();

    int age = dis.readInt();

    double salary = dis.readDouble();

    user.set(id, name, age, salary);

    System.out.println(user);

     

    dis.close();

}


总结

  • Hadoop内部也有一套自己的序列化框架:提供了一个接口Writable
  • 我们的类只要实现了Writable接口,hadoop内部就能用自己的序列化机制去序列化这个类的对象


更多学习资料可关注:annalin1203获取

发布了969 篇原创文章 · 获赞 5 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/u010395024/article/details/105628664