目前有这个需求,需要将java跑好的结果持久化,但是如果一个个输出为文本文件又不太好办,因为里面东西太多太杂,所以最好的办法是直接输出为二进制文件,把数据连同存储数据的类一起存进去,就行python中的pickle类所做的一样。
在网上转了一圈,大部分是讲如何输出为文本文件的,所以在经过查询和调试以后,给出我自己的方法。
要实现这个功能主要有两点,一是FileOutputStream和ObjectOutputStream的搭配使用,一是Serializable接口的实现。
1.FileOutputStream和ObjectOutputStream的搭配使用
File file = new File(".\\test.dat") ; // 建立文件
try{
TestClass tc = new TestClass(5,"akldsj") ;
if (!file.exists()) file.createNewFile() ;
FileOutputStream fos = new FileOutputStream(file) ;
ObjectOutputStream oos = new ObjectOutputStream(fos) ;
oos.writeObject(tc);
System.out.println("文件已存入");
oos.close();
fos.close();
}catch (IOException e){
e.printStackTrace();
}
其中TestClass对象tc就是我们要存入的内容。
同理,如果要取出来,则需要FileInputStream和ObjectInputStream的配合
try{
FileInputStream fis = new FileInputStream(file) ;
ObjectInputStream ois = new ObjectInputStream(fis) ;
TestClass tc = (TestClass)ois.readObject() ;
System.out.println(tc);
ois.close();
fis.close();
}catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
2.Serializable接口的实现
对于自定义类,如果直接使用上述代码是会报错的,所以需要自己定义的类实现Serializable接口,否则会报java.io.NotSerializableException错误
跑去这个接口的定义里发现似乎并没有要自己实现的方法。但是这边要注意有一个很容易忽略的地方,就是serialVersionUID
简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
serialVersionUID有两种显示的生成方式:
一个是默认的1L,比如:
private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
这边采用前一种方法。
class TestClass implements Serializable{
private static final long serialVersionUID = 1L ;
private int a ;
private String b ;
TestClass(int a, String b){
this.a = a ;
this.b = b ;
}
public String toString(){
return String.valueOf(a) + b ;
}
}
最后得到程序的运行结果是
文件已存入
5akldsj
可以看到文件存入后又读出成功,且可以直接使用