Java的IO操作(三) - 对象的序列化、ObjectInputStream和ObjectOutputStream类
2013-04-01 10:18
281 查看
由于Java是一种完全面向对象的高级语言,所以在编写程序的时候数据大都存放在对象当中。我们有时会需要将内存中的整个对象都写入到文件中去,然后在适当的时候再从文件中将对象还原至内存。我们可以使用java.io.ObjectInputStream和java.io.ObjectOutputStream类来完成这个任务。
1、对象的序列化(Serialize)
序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
2、ObjectInputStream类 和ObjectOutputStream类
如果我们想要序列化一个对象,如我们自定义的User类的对象,那么这个对象必须实现Serializable接口。Serializable接口没有任何的抽象方法,实现这个接口仅仅是为了通知编译器这个对象将要被序列化而已。类似的用法还有Cloneable接口,实现这个接口也只是起到通知编译器的作用。
为了演示如何进行对象的序列化,我们先设计一个User类:
注意,seriaVersionUID是指可序列化对象的版本。如果我们没有指定这个版本,那么编译器为自动为实现Serializable接口的类产生一个seriaVersionUID。如果是自动产生的,那么一次如果更改了User类,则自动产生的seriaVersionUID就会不同。在从文件中读回对象时,如果两个对象的seriaVersionUID不同,就会抛出java.io.InvalidClassException。因此如果我们今后不需要改动User类的话,最好自己指定seriaVersionUID,以防止发生该异常。
下面我们使用ObjectInputStream类 和ObjectOutputStream类 向文件中写入3个User对象,追加1个User对象,最后再从文件中读回对象。
注意,当我们想要向一个已经存在的文件中追加对象时,应该重写ObjectOutputStream的writeStreamHeader()方法,并空实现。因为,ObjectOutputStream在写入数据的时候会加上一个特别的流头(Stream Header),在读取数据的时候会先检查这个流头。所以我们在向文件中追加对象的时候ObjectOutputStream就会再次向文件中写入流头,这样在读取对象的时候会发生StreamCorrupedException异常。
1、对象的序列化(Serialize)
序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
2、ObjectInputStream类 和ObjectOutputStream类
如果我们想要序列化一个对象,如我们自定义的User类的对象,那么这个对象必须实现Serializable接口。Serializable接口没有任何的抽象方法,实现这个接口仅仅是为了通知编译器这个对象将要被序列化而已。类似的用法还有Cloneable接口,实现这个接口也只是起到通知编译器的作用。
为了演示如何进行对象的序列化,我们先设计一个User类:
package cls; import java.io.*; public class User implements Serializable // 实现Serializable接口,仅仅直到标识这个类可被序列化的作用 { // 可序列化对象的版本 private static final long serialVersionUID = 1L; private String name; private int num; public User(String name,int num) { this.name = name; this.num = num; } public String getName() { return name; } public int getNum() { return num; } }
注意,seriaVersionUID是指可序列化对象的版本。如果我们没有指定这个版本,那么编译器为自动为实现Serializable接口的类产生一个seriaVersionUID。如果是自动产生的,那么一次如果更改了User类,则自动产生的seriaVersionUID就会不同。在从文件中读回对象时,如果两个对象的seriaVersionUID不同,就会抛出java.io.InvalidClassException。因此如果我们今后不需要改动User类的话,最好自己指定seriaVersionUID,以防止发生该异常。
下面我们使用ObjectInputStream类 和ObjectOutputStream类 向文件中写入3个User对象,追加1个User对象,最后再从文件中读回对象。
package cls; import java.io.*; import java.util.*; import cls.User; public class ObjectStreamDemo { public static void main(String[] args) { User[] user = new User[]{new User("dogg",1),new User("catt",2),new User("pigg",3)}; // 向文件中写入对象 try { ObjectStreamDemo.writeObj(user,args[0]); } catch(Exception e) { System.out.println(e.toString()); } // 向文件中追加对象 try { // 要追加的对象 User[] u = new User[]{new User("append1",4),new User("append2",5)}; ObjectStreamDemo.appendObj(u,args[0]); } catch(Exception e) { System.out.println(e.toString()); } // 读取对象 try { List<User> list = ObjectStreamDemo.readObj(args[0]); // 输出对象信息 Iterator<User> it = list.iterator(); while(it.hasNext()) { User temp = it.next(); System.out.println(temp.getName() + "," + temp.getNum()); } } catch(Exception e) { System.out.println(e.toString()); } } static private void appendObj(Object[] objs,String fileName) throws Exception { File file = new File(fileName); // 以追加模式创建文件流对象 FileOutputStream fis = new FileOutputStream(file,true); ObjectOutputStream oos = new ObjectOutputStream(fis) { // 重写 writeStreamHeader()方法,空实现 protected void writeStreamHeader(){}; }; // 写入数据 for(Object o : objs) { oos.writeObject(o); } // 关闭流 oos.close(); } static private List<User> readObj(String fileName) throws Exception { File file = new File(fileName); // 使用List保存读取出来的对象 ArrayList<User> list = new ArrayList<User>(); // 创建流对象 FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis); // 读取对象并放入List容器中 while(fis.available() > 0) { list.add((User)ois.readObject()); } ois.close(); return list; // 返回List } static private void writeObj(Object[] objs,String fileName) throws Exception { // 使用命令行参数中指定的文件名 File file = new File(fileName); // 创建流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); // 写入对象 for(Object o : objs) { oos.writeObject(o); } // 关闭流 oos.close(); } }
注意,当我们想要向一个已经存在的文件中追加对象时,应该重写ObjectOutputStream的writeStreamHeader()方法,并空实现。因为,ObjectOutputStream在写入数据的时候会加上一个特别的流头(Stream Header),在读取数据的时候会先检查这个流头。所以我们在向文件中追加对象的时候ObjectOutputStream就会再次向文件中写入流头,这样在读取对象的时候会发生StreamCorrupedException异常。
相关文章推荐
- Java的IO操作(三) - 对象的序列化、ObjectInputStream和ObjectOutputStream类
- Java基础之对象的序列化(持久化)操作对象ObjectInputStream/ObjectOutputStream
- Java IO--对象序列化Serializable、ObjectOutputStream、ObjectInputStream、transient
- Java IO之对象的序列化、ObjectInputStream和ObjectOutputStream类
- Java IO操作——对象序列化(Serializable接口、ObjectOutputStream、以及与Externalizable接口的用法和区别)
- Java IO系列(五):读写对象ObjectOutputStream和ObjectInputStream
- Java使用ObjectOutputStream和ObjectInputStream序列号对象报java.io.EOFException异常的解决方法
- Java_基础—对象操作流ObjecOutputStream/ObjectInputStream
- Java学习笔记——IO操作之对象序列化及反序列化
- java IO操作与字节流(五)对象序列化
- Java对象序列化ObjectOutputStream和ObjectInputStream示例
- java语言编程IO流之对象序列化和ObjectInputStream与ObjectOutputStream
- Java对象序列化ObjectOutputStream和ObjectInputStream示例
- Java-IO之对象输入流输出流(ObjectInputStream和ObjectOutputStream)
- Java IO(十一):序列化与 ObjectInputStream、ObjectOutputStream
- Java对象序列化ObjectOutputStream和ObjectInputStream示例
- (JAVA)从零开始之--对象输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)
- Java-IO之对象输入流输出流(ObjectInputStream和ObjectOutputStream)
- Java-IO之对象输入流输出流(ObjectInputStream和ObjectOutputStream)
- java IO笔记(序列化与ObjectInputStream、ObjectOutputStream)