对象输入输出流ObjectInputStream和ObjectOutputStream
Java的IO中,我们可以对对象进行输入输出来进行保存对象的状态,也就是我们可以在内容和磁盘之间来进行对象的写出和读入:
这里我们需要介绍专属的对象输入输出流ObjectInputStream和ObjectOutputStream两个专属的对象流,其中有两个重要的概念,序列化和反序列化
其中我们对于每个对象的保存都要注意到一个重要的事情:就是自定义的保存的对象一定要实现Serializable接口,这是一个标志性接口不需要我们实现什么抽象方法,这个接口的实现主要是为了告诉虚拟机进行序列化相关的对象输入输出的操作,当我们没有实现这个接口就进行序列化时,会报错的。
import java.io.*;
//定义User类
class User implements Serializable{
int age;
String name;
public User() {
}
public User(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
//主程序
public class dataStreamTest {
public static void main(String[] args) {
User user= new User(12,"zhangsan");
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
FileOutputStream fos =null;
FileInputStream fis=null;
try {
//写出
fos= new FileOutputStream("test.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(user);
//读入
fis= new FileInputStream("test.txt");
ois= new ObjectInputStream(fis);
Object o = ois.readObject();
if(o instanceof User){
User user1=(User)o;
System.out.println(user1);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}finally {
if (oos !=null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
程序运行结果:
test.txt文件
对象流的构造需要传入的是一个基本的节点流对象,所以对象流也是包装流,我们需要调用它的writeObject方法写出对象,readObject方法读入对象!!
序列化多个对象:
User user= new User(12,"zhangsan");
User userII=new User(14,"huahua");
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
FileOutputStream fos =null;
FileInputStream fis=null;
try {
//写出
fos= new FileOutputStream("test.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(user);
oos.writeObject(userII);
//读入
fis= new FileInputStream("test.txt");
ois= new ObjectInputStream(fis);
Object o = ois.readObject();
if(o instanceof User){
User user1=(User)o;
System.out.println(user1);
}
Object o2 = ois.readObject();
if(o2 instanceof User){
User user2=(User)o2;
System.out.println(user2);
}
我们序列化了两个对象,然后反序列化的读出,我们可以考到结果:
可以看出我们可以正确的读出序列化到磁盘的对象!!
换一种方式序列化多个对象我们可以将序列化的对象都存储到一个集合中我们将整个集合对象序列化磁盘文件中,读取的时候读取磁盘文件上的集合对象,再遍历集合来取出对象!!!
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class dataStreamTest {
public static void main(String[] args) {
User user1=new User(12,"zhangsan");
User user2=new User(14,"llisi");
User user3=new User(16,"huahua");
User user4=new User(16,"huihui");
List<User> list=new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
FileOutputStream fos=null;
FileInputStream fis =null;
ObjectInputStream ois = null;
ObjectOutputStream oos= null;
try {
fos =new FileOutputStream("test.txt");
oos= new ObjectOutputStream(fos);
oos.writeObject(list);
oos.flush();
fis = new FileInputStream("test.txt");
ois= new ObjectInputStream(fis);
Object o = ois.readObject();
if (o instanceof List){
List list1 =(List<User>)o;
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
oos.close();
ois.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
结果如下:
我们可以看到,可以正确读取了!!!
最后我们来进行一个关键字的说明transient关键字,这个关键字修饰的属性不参与序列化,也就是说如果我们在某一个属性上加上了transient关键字,这个属性的值不会保存到磁盘上,当我们反序列化的时候读取值为null或者0;
transient:游离的,不参与序列化操作!!!