持久化技术
将内存中的临时数据,保存到本地硬盘的技术;持久化之后,即使程序重启,也不会造成数据的丢失和重置
使用常规的方法将数据存取在文件中
将集合中的数据写入文件
//创建student集合
List<Student> stus = new ArrayList<Student>();
stus.add(new Student(1,"小马",16));
stus.add(new Student(2,"小菜",16));
stus.add(new Student(3,"小希",18));
//将集合中的数据写入文件
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("路径"))));
//向文件中写数据
for(Student stu : stus){
bw.write(stu.getId());
bw.write(stu.getName());
bw.write(stu.getAge());
bw.newLine();
bw.fulsh();
}
/*
查看文件的时候,会发现出了字符串,其他都是乱码,可以使用+""转成字符串
bw.write(stu.getId()+",");//转成字符串
bw.write(stu.getName()+",");
bw.write(stu.getAge()+"");
*/
bw.close();
将文件中的数据存入集合之中
//创建集合存放学生数据
List<Student> stus = new ArrayList<Student>();
//读取学生的数据
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("路径"))));
//存放读出来的每条字符串的数据
String strStu;
while((strStu=br.readLine())!=null){
//文本中每一行的字符串
//1,小马,16
//2,小菜,16
//3,小希,18
//将字符串按照“,”分割,每个字符串会被分成一个字符串数组
String[] strs = strStu.split(",");
//创建学生对象,获取数据
Student stu = new Student();
//strs是第一行字符串以逗号分开的字符串数组,将值对象的传给stu的每 个属性
stu.setId(Integer.parseInt(strs[0]));
stu.setName(strsp[1]);
stu.setAge(integer.parseInt(strs[2]));
//输出学生对象
System.out.println(stu);
//学生对象存入集合之中
stus.add(stu);
}
br.close();
使用序列化技术,进行持久化
使用对象的序列化技术,来进行持久化。简化数据转换的操作,直接将对象的序列化之后存入文档,取出时进行反序列化可直接取出对象,而不用再进行繁琐的字符串操作
-
序列化:
将对象转换成方便传输的流(输出)
- 使用ObjectOutputStream流中的writeObject(obj)的方法,将Obj对象序列化到流中
-
反序列化:
将流转换成对应的对象(输入)
- 使用ObjectInputStream流中的readObject()方法,将流中的对象反序列化为对象
-
注意:
需要传输的对象对应的实体类必须实现序列化接口implements Serializable
- Serializable接口中没有任何属性和方法,仅仅是一个标志,标志着它的实现类可以被序列化而已
序列化,将对象序列化,写入文件
//创建一个对象
Student stu = new Studet(1,"小马",13);
//使用最基础的字节流创建序列化对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("路径")));
//oos.writeObject(stu);
oos.close();
//此时文件中存储的内容任然是乱码,但是程序反序列化时可以识别这些数据,将这些数据完整的转换成原来的对象
反序列化,文件中的内容取出来反序列化成对象
//创建读取的反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("路径")))
//readObject方法返回的是一个对象
Student getStu = (Student)ois.readObjet();
//反序列化取出的可以取出对象,替代了繁琐的数据转换的操作,直接一步到位,读取出来就是一个对象
序列化ID
serialVersionUID,作为唯一标识,一般实现是程序化接口时,会把这个作为常量加入到实体类中,用来判断这个类的对象没有被修改过,防止程序修改了对象数据造成文件和程序对象数据不一致
反序列化一次读取多个对象
1.创建自定义类
创建自定义类,继承ObjectOutputStream类,重写里面的writeStreamHeader()方法
/**
* 使用序列化写入对象时,如果是第一次写入文件(文件为空)
* 就用objectOutputStream写对象,会写入一个头标记
* 如果不是第一次,就用自定义类写对象,就不会写入头标记
*/
//自定义一个类叫SubObjOutputStream,继承ObjectOutputStream
public class SubObjOutputStream extends ObjectOutputStream{
//调用父类的构造方法
public SubObjOutputStream(OutputStream out) throws IoException{
super(out);
}
//重写父类中的写头标记的方法
//每次调用writeObject写入对象时都会先调用此方法,安子文就按中写入头标记
//但是一个文件中只需要一个头标记即可,文件你中有多个头标记会报异常
@Override
protected void writeStreamHeader() throws IOException{
//注释掉,不让他写头标记
//super.writeStreamHeader();
}
}
2.序列化对象
public class Demo01{
public static void main(String[] args)throws Exception{
FileOutputStream fos = new FileOutputStream("test.txt",true);//字节流,true代表可以追加写入
//声明一个序列化对象
ObjectOutputStream oos = null;
//先获取路径文件的test.txt
File f = new File("test.txt");
//如果文件的长度小于1,代表这个文件是空的,第一次写入文件
if(f.length()<1){
//使用ObjectOutputStream来序列化对象
oos = new ObjectOutputStream(fos);
}else{
//如果里面有对象,就是用SubObjOutputStream来序列化对象
//使用SubObjOutputStream序列化对象,不会待遇头标记
oos = new SubObjOutputStream(fos);
}
User user = new User(3,"小希",18);
//将对象存入
oos.writeObject(user);
//关流
oos.close();
}
}
3.反序列化读取多个对象
public class Demo02{
//反序列化
public static void main(String[] args)throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("路径"));
//单条输出输出
User u1 = (user)ois.readObject();
USer u2 = (user)ois.readObject();
//取消多余头标记后可以正常输出两个对象
System.out.println(u1);
System.out.println(u2);
/**
* 反序列化时,如果只有两条数据反序列化,读取次数超过2次的话就会异常
* 如何依次输出说有的对象
* 要使用异常捕获,一旦读取完毕就给提示
*/
try{
Object obj = null;
while((obj=ois.readObject())!=null){
User user = (User)obj;
System.out.println(user);
}catch(EOFException e){
System.out.println("读取完毕");
}
}
ois.close();
}
}