序列化流和Properties类的操作
1、(序列化流)ObjectOutputStream:可以将java对象的基本数据类型写入OutputStream,所以可以将java对象通过该流写入文件中。
主要方法: void writeObject(Object obj)
2、(反序列化流)ObjectInputStream:可以使用 ObjectInputStream 读取(重构)对象,可以将已序列化的对象读取。
主要方法: Object readObject()
3、Properties:表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
public class Properties extends Hashtable<Object,Object>
该类是继承Hashtable,但它不是泛型类,K和V的类型为Object
特有方法:
String getProperty(String key)
用指定的键在此属性列表中搜索属性。
void load(InputStream inStream)
void load(Reader reader)
从输入流中读取属性列表(键和元素对)。
void store(OutputStream out, String comments)
void store(Writer writer, String comments)
将此 Properties 表中的属性列表(键和元素对)写入输出流。
一、序列化流
static void out() {
try {
FileOutputStream fos = new FileOutputStream("src\\file\\paper.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
User user = new User(001,"李华" , "北京");
oos.writeObject(user);
}catch(IOException e) {
e.printStackTrace();
}
}
输出:
报了一个NotSerializableException异常,当实例需要具有序列化接口时,抛出此异常。序列化运行时或实例的类会抛出此异常。所以,我们的User类应该事先该接口Serializable
接下来输出:
这是序列化后的结果,看不懂是正常的。
二、反序列化
static void in() {
try {
FileInputStream fis = new FileInputStream("src\\file\\paper.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Object object = ois.readObject();
User user = (User)object;
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}
}
如果我们修改对象所在类,能否在反序列化文件呢?
结果:
报了异常InvalidClassException,根据JDK文档以下情况会报此异常:
- 该类的序列版本号与从流中读取的类描述符的版本号不匹配
- 该类包含未知数据类型
- 该类没有可访问的无参数构造方法
根据User类,我们可以排除后面两个问题,所以是第一个问题。我们回头看Serializable接口发现以下解释:
1、
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。
2、
如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java™ 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值。
由上我们可以得知,在对对象反序列化,会对serialVersionUID值进行验证,而修改对象的所在内,serialVersionUID的值会改变,所以我们需要为类设置一个serialVersionUID值。
结果:
如果需要User类中的一个成员变量不可序列化,则需要对它用transient进行修饰。
三、Properties类与IO流
将Properties集合中的数据通过store方法写入文件中
Properties properties = new Properties();
properties.put("1", "特工1号");
properties.put("2", "特工2号");
properties.put("3", "特工3号");
properties.put("4", "特工4号");
try {
properties.store(new FileWriter("src\\file\\paper.txt"), null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
结果:
将文件中的数据读取放入Properties集合中
Properties properties = new Properties();
try {
properties.load(new FileReader("src\\file\\paper.txt"));
System.out.println(properties);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}