对象流写入读出

将对象写入文件经历两个步骤:
1.通过对象输出流将person首先转换为了一组字节,这个过程称为:对象序列化
2.将序列化后的字节再通过fos写入到文件(硬盘上)做长久保存的过程称为:数据持久化

对象流用于对象序列化(将一个对象按结构转换为一组字节的过程),文件流用于对象持久化(将对象写入硬盘的过程)

当前类的实例若希望被对象流读写,那么就必须实现java.io.Serialiazable接口,并且当前类中所有引用类型的属性它们的类也必须都实现该接口。
当一个类实现了Serialiazable接口,那么在编译的时候,编译器会隐含的在class文件中添加一个方法,用于将当前对象转换为一组字节。

当一个类实现了Serialiazable接口后应当定义一个常量:serialVersionUID
它是序列化版本号,若不指定,编译器会在编译当前类时根据当前类的结构生成一个版本号。
版本号决定反序列化当前类实例时是否可以成功,当版本号一致时反序列化成功, 不一致时对象输入流在进行反序列化时会抛出异常。

若当前类结构发生改变,但是版本号没有变化的前提下,原来的对象是可以反序列化的,这是会采取兼容模式,即:还原原有属性。
/*
 *  当一个属性被transient修饰后,那么该属性在对象序列化时会被忽略
 */

首先创建一个实例化后的对象。注意实现序列化接口,且重写toString等方法。

写入的文件大小与实际写入字节数不一致,原因是在序列化的过程当中,会保留该对象的结构,占据了一定得字节量。


在写入对象文件的过程中,采用了txt文件,发现文件乱码,引发了思考。

  首先需要理解好IO流是如何处理文件的。

1.ObjectOutputStream 对Java对象进行序列化处理,处理后的数据,不是文本数据,
   所以,该数据保存到文件中,用文本编辑器打开,必然是乱码。
2.输出流,在写入之后,一般都会调用flush方法,将缓冲区的数据刷到IO中去
   (当然,楼主的目的地是硬盘文件中)。IO读写,一般情况下,操作系统也会建立一定大小的缓冲区。
3.输出流,在所有写入操作都做完后,应该关闭IO流,调用close方法。
    除了可以回收系统资源外,也会强制刷新系统缓冲区中的数据至硬盘。
4.object_in引用对应的是输入流对象,流是流动的,当你上面写入一个对象到文件中后,
    下面就只能从那个文件中读取一个对象,再调用读取方法,什么也读不到。
    所以,System.out.println(object_in.readObject());的参数应该是li。
5.输入流在读取完成后,也要进行关闭,回收系统资源。


最后,针对之前说的乱码问题,我上面已经说明了,
各位应该仔细理解Java对象的序列话操作到底干了什么。
它不是简单的把对象属性值写入IO流中,而是按照一定的数据格式写入的。
而这种格式,不是记事本、写字板、Word等文本编辑器能够识别的,
因为,这些数据,压根就不是文本数据。
只有使用相同版本的Java的ObjectInputStream来进行读取操作。
并且,流数据,在没有缓冲区的情况下,是不能读取重复数据的。
也就是说,如果,我的文本文件中,存放12345这五个字符,
那么,我用流读取一个字符,第一个是字符1,第二次读取,必然是字符2,
不可能还是字符1,除非你用带缓冲区缓的流对象,这样,你在读取前先做标记,
读取完了,可以回退到标记处,重复读取数据,
当然,数据的当前位置和标记位置之间的距离不能超过缓冲区的大小。


文件输入流,读取字节并还原为指定的对象

ObjectInputStream提供方法:

Object readObject()

该方法可以读取字节并还原为指定的对象,需要确保OIS读取的字节是通过对象输出流(OOS)将一个对象写出的字节,否则是会抛出异常的。


  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值