编程语言的基础——搞定JavaIO (6)

这一对类可以直接写入java基本类型数据(没有String),但写入以后是一个二进制文件的形式,不可以直接查看。DataOutputStream / DataInputStream是常用的过滤流类,如果对象的序列化是整个对象转换为一个字节序列的话,DataOutputStream / DataInputStream就是将字段序列化,转为二进制数据。下面看代码。

package javaS.IO; +import java.io.BufferedInputStream; public class DataStream extends IOBaseS { @Test /** * DataOutputStream,可以直接写入java基本类型数据(没有String),但写入以后是一个二进制文件的形式,不可以直接查看。 * * 文本文件是二进制文件的特殊形式,这是通过转储实现的,相关内容请转到 * #二进制转储 */ public void testWrite2DataOutputStream() throws IOException { OutputStream fosaddOnce = new FileOutputStream(root + "/UME.txt"); OutputStream bs = new BufferedOutputStream(fosaddOnce); DataOutputStream dos = new DataOutputStream(bs); dos.writeInt(22); dos.writeShort(1222222222); dos.writeLong(20L); dos.writeByte(3); dos.writeChar(42); dos.close(); bs.close(); fosaddOnce.close(); /** * 终版:上面的close阶段要从内向外关闭三次,比较麻烦,下面直接采用装饰模式标准写法,套接对象。 * 套接对象:最里面的一定是节点流,它之外的无论几层都是处理流 * FileOutputStream:属于节点流,其他节点流还包括管道和数组,剩下的都是处理流 * BufferedOutputStream:缓冲技术(也属于处理流) DataOutputStream:处理流 */ DataOutputStream dosA = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(root + "/UME.txt"))); dosA.writeInt(22); dosA.writeShort(65538);// DataOutputStream并不会检查数据是否越界,越界的数据按照二进制方式截取,只保留界限以内的数据。 dosA.writeLong(20L); dosA.writeByte(3); dosA.writeChar(42); dosA.writeDouble(3.1415926); dosA.close();// 只关闭一次。 } @Test /** * 通过DataInputStream处理流读取二进制文件,一定要按照写入的顺序去读取java基本类型的文件内容,否则会出现乱码或者不准确的信息 */ public void testRead2DataInputStream() throws IOException { DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(root + "/UME.txt"))); logger.info(dis.readInt()); /** * 即使存入越界的树65538,也不会报错,因为超出部分不会被存入,存入的只是超出的部分。 * short类型占据16位的空间,因此将65538转为二进制数,超出16位的部分自动截掉,只保留16为以内的数据,所以就变成了2。 */ logger.info(dis.readShort()); logger.info(dis.readLong()); logger.info(dis.readByte()); logger.info(dis.readChar()); logger.info(dis.readDouble()); dis.close(); /** * 输出: * 13:39:03[testDataInputStream]: 22 * 13:39:03[testDataInputStream]: 2 * 13:39:03[testDataInputStream]: 20 * 13:39:03[testDataInputStream]: 3 * 13:39:03[testDataInputStream]: * * 13:39:03[testDataInputStream]: 3.1415926 */ } }

注释比较齐全,这里不再过多赘述。

三、对象流 / 序列化

数据传输过程中,都会默认采用二进制文件的方式,因为计算机的底层识别方式就是二进制,不依赖任何运行环境或是程序设计语言,所以这是实现数据传输跨平台跨网络的基础。序列化可以直接将java对象转化为一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象,这一过程甚至可以通过网络进行,这意味着序列化机制能自动弥补不同操作系统之间的差异。

如果要让一个类的对象可以成功序列化,那么它必须实现Serializable接口,这个接口就像Cloneable接口一样,他们只是一个空的标识接口。

下面这段话用来描述对象序列化真的非常受启发。

当你创建对象时,只要你需要,它就会一直存在,但是在程序终止时,无论如何它都不会继续存在。尽管这么做肯定是有意义的,但是仍旧存在某些情况,如果对象能够在程序不运行的情况下仍能存在并保存其信息,那将非常有用。这样,在下次运行程序时,该对象将被重建并且拥有的信息与在程序上次运行时它所拥有的信息相同。当然,你可以通过将信息写入文件或数据库来达到相同的效果,但是在使万物都成为对象的面向对象的精神中,如果能够将一个对象声明是“持久性”的,并为我们处理掉所有细节,那将会显得十分方便。

相对于数据库存储那种重量级持久性来说,对象的序列化可以实现轻量级持久性。

持久性意味着一个对象的生命周期并不取决于程序是否正在执行,它可以生存于程序的调用之间。

轻量级是因为不能用某个关键字来简单定义一个对象,并让系统自动维护其他细节问题,相反,对象必须在程序中显示地序列化和反序列化。

如果需要一个更严格的持久性机制,可以考虑像Hibernate之类的工具。TODO: 会有一篇文章深入介绍Hibernate。

对象序列化的意义:

支持java的远程方法调用RMI,它使存活于其他计算机上的对象使用起来就像是存活在本机上一样。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxpgs.html