Java IO(六) ObjectInputStream 和 ObjectOutputStream

一、介绍

对于对象数据的处理,Java IO 提供了 ObjectInputStream 和 ObjectOutputStream 来序列化和反序列对象数据。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久性存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

(一)、ObjectInputStream

创建输出流对应的 ObjectOutputStream 对象,该ObjectOutputStream对象能提供对基本数据或对象的持久性存储。

(二)、ObjectOutputStream

当我们需要读取这些存储的基本数据或对象时,可以创建输入流对应的 ObjectInputStream,进而读取出这些基本数据或对象。如果流是网络套接字流,则可以在另一台主机上或另一个进程中反序列化对象。

注意: 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能被 ObjectInputStream / ObjectOutputStream 所操作!

二、序列化与反序列化

Java是一种完全面向对象的高级语言,所以在编写程序的时候数据大都存放在对象当中。我们有时会需要将内存中的整个对象都写入到文件中去,然后在适当的时候再从文件中将对象还原至内存。我们可以使用ObjectInputStream 和 ObjectOutputStream 类来完成这个任务。

(一)、序列化和反序列化概念

列化是指将对象的状态信息转换为可以存储或传输的形式(2进制数据)的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

(二)、序列化和反序列化的特点

  • 永久保存对象。将对象的字节序列保存到文件中。
  • 通过序列化可以在网络中传递对象数据。
  • 通过序列化可以在进程中传递对象数据。

(三)、序列化与反序列化过程

(四)、serialVersionUID

在对象进行序列化或者反序列化操作的时候,要考虑序列化版本的问题,如果序列化的版本和反序列化的J版本不统一则就可能造成异常,所以在序列化操作中引入了一个serialVersionUID的常量,可以通过此常量来验证版本的一致性,在进行反序列化时,JVM会将传过来的字节流中的serialVersionUID与本地相应实体的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就抛出不一致的异常。

(五)、序列化了哪些数据呢

所有的对象拥有各自的属性值,但是所有的方法都是公共的,所以序列化对象的时候实际上序列化的就是属性。

注意,当我们想要向一个已经存在的文件中追加对象时,应该重写ObjectOutputStream的writeStreamHeader()方法,并空实现。因为,ObjectOutputStream在写入数据的时候会加上一个特别的流头(Stream Header),在读取数据的时候会先检查这个流头。所以我们在向文件中追加对象的时候ObjectOutputStream就会再次向文件中写入流头,这样在读取对象的时候会发生StreamCorrupedException异常。

(六)、Serializable 接口和 Externalizable 接口

1、Serivlizable接口

Serializable接口仅仅定义了接口,里面并没有代码实现,只作为标识,如果一个自定义类实现了 Serializable 接口,说明此类是可以序列化的。

2、Externalizable 接口

如果现在用户希望可以自己制定序列化的内容,则可以让自定义类实现 Externalizable 接口,然后分别实现 public void writeExternal(ObjectOutput out) 和  public void readExternal(ObjectInput in) 方法。

3、Externalizable 和 Serializable接口区别

  • 实现复杂度。Serializable实现简单,Java对其有支持;Externalizable复杂,需要程序员分别实现 public void writeExternal(ObjectOutput out) 和  public void readExternal(ObjectInput in) 方法。
  • 执行效率。Serializable 中所有对象数据有Java保存,效率高;Externalizable 中对象数据有开发者保存,效率较低。
  • 保存空间。Serializable 中所有对象数据都会保存,占用空间大;Externalizable 中保存对象数据由开发者决定,保存空间可大可小。

(七)、transient 关键字

在序列化操作的时候,如果某个属性不希望被序列化,则可以直接使用 transient 关键字声明。

三、构造方法

(一)、ObjectInputStream

(二)、ObjectOutputStream

四、常用API

(一)、ObjectInputStream

(二)、ObjectOutputStream

五、实例

private static final String TMP_FILE = "person.tmp";
public static void main(String[] args) {
  write();
  read();
}
// ObjectOutputStream
private static void write() {
  ObjectOutputStream oos = null;
  try {
    oos = new ObjectOutputStream(new FileOutputStream(TMP_FILE));
    oos.writeBoolean(true);
    oos.writeByte((byte)65);
    oos.writeChar('a');
    oos.writeInt(20131015);
    oos.writeFloat(3.14F);
    oos.writeDouble(1.414D);
    // 写入HashMap对象
    HashMap map = new HashMap();
    for (int i = 0; i < 3; i++) {
      map.put("demo"+i, i);
    }
    oos.writeObject(map);
    Person person = new Person("xiaoming", 20);
    oos.writeObject(person);
  } catch (Exception ex) {
    ex.printStackTrace();
  }finally {
    try {
      if(oos != null) {
        oos.close();
      }
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
} // ObjectInputStream
private static void read() {
  ObjectInputStream ois = null;
  try {
    ois = new ObjectInputStream(new FileInputStream(TMP_FILE));
    System.out.println("boolean : " + ois.readBoolean());
    System.out.println("byte : " + (ois.readByte()&0xff));
    System.out.println("char : " + ois.readChar());
    System.out.println("int : " + ois.readInt());
    System.out.println("float : " + ois.readFloat());
    System.out.println("double : " + ois.readDouble());
    // 读取HashMap对象
    HashMap map = (HashMap) ois.readObject();
    Iterator iter = map.entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry entry = (Map.Entry)iter.next();
      System.out.println(entry.getKey() +"--" + entry.getValue());
    }
    Person person = (Person) ois.readObject();
    System.out.println("person: " + person);
  } catch (Exception e) {
    e.printStackTrace();
  }finally {
    try {
      if(ois != null) {
        ois.close();
      }
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
}

Java IO(六) ObjectInputStream 和 ObjectOutputStream的更多相关文章

  1. Java之IO(七)ObjectInputStream和ObjectOutputStream

    转载请注明源出处:http://www.cnblogs.com/lighten/p/7003536.html 1.前言 本章介绍Java字节流中重要的成员,对象流ObjectInputStream和O ...

  2. java IO(六):额外功能处理流

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. 系统学习 Java IO (六)----管道流 PipedInputStream/PipedOutputStream

    目录:系统学习 Java IO---- 目录,概览 PipedInputStream 类使得可以作为字节流读取管道的内容. 管道是同一 JVM 内的线程之间的通信通道. 使用两个已连接的管道流时,要为 ...

  4. Java IO: 序列化与ObjectInputStream、ObjectOutputStream

    作者:Jakob Jenkov  译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中的序列化以及涉及到的流,主要包括ObjectInputStream和O ...

  5. Java精选笔记_其他IO流(ObjectInputStream、DataInputStream、PrintStream、标准输入输出流)

    其他IO流 ObjectInputStream和ObjectOutputStream 如果希望永久将对象转为字节数据写入到硬盘上,即对象序列化,可以使用ObjectOutputStream(对象输出流 ...

  6. 关于Java IO流学习总结

    一.IO流的三种分类方式 1.按流的方向分为:输入流和输出流 2.按流的数据单位不同分为:字节流和字符流 3.按流的功能不同分为:节点流和处理流     二.IO流的四大抽象类: 字符流:Reader ...

  7. 高级Java工程师必备 ----- 深入分析 Java IO (三)

    概述 Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要考虑和哪种媒介进行IO( ...

  8. 系统学习 Java IO ---- 目录,概览

    Java IO 类的系统教程,原创.主要参考自英文教程 Java IO Tutorial 和 Java Doc. http://tutorials.jenkov.com/java-io/index.h ...

  9. Java——IO流 对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream

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

随机推荐

  1. RobotFrameWork 自动化环境搭建(基于 python2.7)

    1.自动化工具安装顺序 robot Framework(两个RF框架) WXpython(不要更改安装路径,自动安装在python文件中) 安装依赖库 RF3.0 和 RF1.5.2.1 打开 rid ...

  2. D. Kefa and Dishes(状压)

    永久打开的传送门 \(这次总算没有写砸........\) \(设f[i][j]为上一次吃的i物品状态为j的最大收益\) \(那么我们就暴力枚举所有状态i,然后在当前状态找出一个没吃的食物j,再去找一 ...

  3. E. Count The Blocks

    E. Count The Blocks 这是一个计数题,又把我卡自闭了...之前也碰到过类似的题目,这次居然还没有写出来,感觉自己还是太菜了,加油补题吧. 题目大意: 给你一个数字 \(n\),代表的 ...

  4. Collection接口【集合】和Iterator迭代器类

    1.1集合的概述 前面基础学习并使用过集合ArrayList<E>,那么集合究竟是什么呢? 集合:集合是Java中提供的一种容器,可以用来存储多个数据. 那么意思就是说集合是容器,但是容器 ...

  5. u-boot 移植(一)编译环境搭建

    u-boot 移植(一)编译环境搭建 soc:s3c2440 board:jz2440 uboot:u-boot-2016.11 toolchain:gcc-linaro-7.4.1-2019.02- ...

  6. C# 获取从1月至12月的月初时间和月末时间

    public IActionResult GetMonthData() { var dataList = new List<object>(); var currentMonth = Da ...

  7. 散列表PTA判断

    1-1 在散列表中,所谓同义词就是具有相同散列地址的两个元素. (1分) T         F 作者 DS课程组 单位 浙江大学   1-2 采用平方探测冲突解决策略(h​i​​(k)=(H(k)+ ...

  8. xsser和XSStrike

    0x01 xsser xsser是一款用于针对Web应用程序自动化挖掘.利用.报告xss漏洞的框架.kali默认安装. 命令行启动:xsser 图形化界面启动:xsser --gtk 帮助信息:xss ...

  9. 两种方式实现sticky footer绝对底部

    一.什么是sticky footer 如果页面内容不够长的时候,页脚块粘贴在视窗底部:如果内容足够长时,页脚块会被内容向下推送,我们看到的效果就如下面两张图这样.这种效果基本是无处不在的,很受欢迎. ...

  10. SpringCloud Netflix (五) : Hystrix 服务熔断和服务降级

    什么是Hystrix 在分布式环境中,许多服务依赖项中的一些服务依赖不可避免地会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务 ...