序列化和文件的输入输出
-
存储状态的选择
-
如果只有自己写的Java程序会用到这些数据:
用序列化:
将被序列化的对象写到文件中。然后就可以让你的程序去文件中读取序列化的对象并把它们展开回到活生生的状态
-
如果数据需要被其他程序引用:
写一个纯文本文件。用其他程序可以解析的特殊字符写到文件中
-
-
将串流连接起来代表来源与目的地的连接。串流必须要链接到某处才能算是个串流
-
Java的输入/输出API带有连接类型的串流,它代表来源于目的地之间的连接,连接串流将串流与其他串流连接起来
-
一般来说,串流要两两连接才能作出有意义的事情—其中一个表示连接,另一个则是要被调用方法的
-
序列化的对象保留了实例变量的值
-
当对象被序列化时,被该对象引用的实例变量也会被序列化,且所有被应用的也会被序列化,这些操作都是自动进行的
-
Serializable接口又被称为marker或tag类的标记用接口,因为此接口并没有任何方法需要实现的。它的唯一目的就是声明有实现它的类是可以被序列化的。如果某类是可序列化的,则它的子类也自动的可以序列化
-
序列化是全由或全无的,整个对象版图都必须正确的序列化,不然就得全部失败
-
如果某实例变量不能或不应该被序列化,就把它标记为transient的
-
将序列化对象写入文件
- 创建出FileOutputStream
- 创建ObjectOutputStream
- 写入对象
- 关闭ObjectOutputStream
FileOutputStream fileStream = new FileOutputStream("MyGame.ser");
ObjectOutputStream os =new ObjectOutputStream(fileStream);
os.writeObject(characterOne);
os.writeObject(characterTwo);
os.writeObject(characterThree);
os.close();
- 解序列化:还原对象
- 创建FileInputStream
- 创建ObjectInputStream
- 读取对象
- 转换对象类型
- 关闭ObjectInputStream
FileInputStream fileStream = new FileInputStream("MyGame.ser");
ObjectInputStream os =new ObjectInputStream(fileStream);
Object one =os.readObject;
Object two =os.readObject;
Object three =os.readObject;
GameCharacter elf=(GameCharacter) one;
GameCharacter troll=(GameCharacter) two;
GameCharacter magician=(GameCharacter) three;
os.close();
- 静态变量不会被序列化,因为所有对象都是共享同一份静态变量值
- 读取对象的顺序必须与写入的顺序相同
- 输入/输出相关的操作都必须包在try/catch块中
- File对象代表磁盘上的文件或目录的路径名称,但它不能读取或代表文件中的数据
- File的操作
- 创建出代表现存盘文件的File对象
- 建立新的目录
- 列出目录下的内容
- 取得文件或目录的绝对路径
- 删除文件或目录
- 读取是以while循环来逐行进行,一直到readLine()的结果为null为止
- 缓冲区利用**BufferedWriter 来提高效率,它可以暂存一堆数据,然后到满的时候再实际写入磁盘,这样就可以减少磁盘操作的次数,如果想要强制缓存区立即写入,只要调用writer.flush()**就可以了
- String的split()可以把字符串拆开,其中的分割字符不会被当作数据看待
- 会损害解序列化的修改:
- 删除实例变量,改变实例变量的类型,将非瞬时的实例变量改为瞬时的
- 改变类的继承层次,将类从可序列化改变成不可序列化
- 通常不会有事的修改:
- 加入新的实例变量
- 在继承层次中加入新的类,从继承层次中删除类
- 不会影响序列化程序设定变量值的存取层次修改
- 将实例变量从瞬时改成非瞬时
- 每当对象被序列化的同时,都会有一个ID(serialVersionUID),当Java尝试要还原对象时,它会对比对象与Java虚拟机上的类的serialVersionUID,如果版本不相符,Java虚拟机就会在还原过程中抛出异常
- 若想知道某个类的serialVersionUID,则可以使用Java Development Kit 里面所带的serialver工具来查询