对象的序列化与反序列化
对象的序列化与反序列化(对象流)
作用:将java对象写入到数据源中,也能把对象从数据源中还原
- 序列化:ObjectOutputStream类 保存 基本类型数据或对象的机制 (写出到文件)
- 反序列化:ObjectInputStream类 读取 基本类型数据或对象的机制 (写入到内存)
ObjectOutputStream,ObjectInputStream 不能序列化static和 transient 修饰的成员变量
对象的序列化
- 把内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或通过网络这种二进制流传输到另一个网络节点。当其他城西获取这种二进制流,就可以恢复成原来的对象(反序列化)
- 序列化的好处在于可以将实现了Serializable接口的对象转换成字节数据,使其在保存和传输时可被还原
- 序列化时RMI(Remote Method Invoke - 远程调用) 过程的参数和返回值都必须实现的机制,而RMI和JavaEEs的基础。因此序列化机制是JavaEE平台的基础
- 如果需要让某个对象支持序列化机制,则必须让对象所属的类其属性是可序列化的,为了让某个类的可序列化的,该类必须实现两个接口之一。
- Serializable
- Externalizable
- 凡是实现序列化接口的类都必须要有个序列化版本标识符的静态变量:
-
serialVersionUID 用来表明类的不通版本的兼容性,就是以序列化对象进行版本控制。有关各版本反序列化时是否兼容
- 如果没定义 serialVersionUID ,java运行时会自动生成。但是如果这时实列变量做了修改,serialVersionUID也可能会发生变化。这时候就会导致反序列化失败
-
@Data public class Student implements Serializable{
private static final long serialVersionUID = 1L; private Integer id; private String name; private Integer age; private String sex; }
package com.pw.studydemo.objStream; import org.junit.Test; import java.io.*; /** * * 对象流(序列化) * @author pw * @version 1.0 * @date 2022/7/14 14:55 */ public class ObjectInputStreamNo1 { /** * 序列化,将内存中对象写入磁盘文件 */ @Test public void objOutput(){ ObjectOutputStream oos = null; try { Student student = new Student(); student.setId(1); student.setName("枫林玉"); student.setAge(24); // student.setSex("女"); oos = new ObjectOutputStream(new FileOutputStream(new File("studentObj.dat"))); oos.writeObject(student); oos.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if (oos != null){ try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 反序列化,将磁盘文件对象读入内存 */ @Test public void objInput(){ ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(new File("studentObj.dat"))); Student s = (Student) ois.readObject(); System.out.println(s.toString()); } catch (IOException e) { e.printStackTrace(); }catch (ClassNotFoundException e) { e.printStackTrace(); }finally { if(ois != null){ try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
随机存取文件流
package com.pw.studydemo.randomStream; import org.junit.Test; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * * RandomAccessFile 是直接集成 Object 并且实现了 DataOutput, DataInput接口 * 既可以做输入流也可以做输出流(操作时,一个类两个对象) * * 在做输出流时,写出文本 * 1. 文件不存在时,直接创建 * 2. 文件存在时,在文本内容从头开始覆盖 * * @author pw * @version 1.0 * @date 2022/7/14 16:11 */ public class RandomAccessFileNo1 { @Test public void randomAccess(){ RandomAccessFile rafInput = null; RandomAccessFile rafOutput = null; try { // 1. 创建流对象 rafInput = new RandomAccessFile(new File("D:\\soft\\1.jpg"),"r"); rafOutput = new RandomAccessFile(new File("D:\\soft\\2.jpg"),"rw"); // 2. 读写过程 byte[] buffer = new byte[1024]; Integer len; while ((len = rafInput.read(buffer)) != -1){ rafOutput.write(buffer,0,len); } } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); }finally { // 3. 关流 if(rafOutput != null){ try { rafOutput.close(); } catch (IOException e) { e.printStackTrace(); } } if(rafInput != null){ try { rafInput.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 覆盖 * @throws IOException */ @Test public void randomAccessWrite() throws IOException{ RandomAccessFile randomAccessFile = new RandomAccessFile("text.txt","rw"); randomAccessFile.write("666".getBytes()); randomAccessFile.close(); } /** * 在文件文本内容后追加 * @throws IOException */ @Test public void randomAccessWrite2() throws IOException{ File file = new File("text.txt"); RandomAccessFile randomAccessFileOutput = new RandomAccessFile(file,"rw"); // 先拿到这文件的长度,将“指针”调制最后 randomAccessFileOutput.seek(file.length()); randomAccessFileOutput.write("abc".getBytes()); randomAccessFileOutput.close(); } /** * 内容处插入 * @throws IOException */ @Test public void randomAccessWrite3() throws IOException{ File file = new File("text.txt"); RandomAccessFile randomAccessFileInput = new RandomAccessFile(file,"r"); RandomAccessFile randomAccessFileOutput = new RandomAccessFile(file,"rw"); byte[] bytes = new byte[1024]; // 定义插入位置下标 int insert = 3; int read = randomAccessFileInput.read(bytes); byte[] bytes2 = new byte[read - insert]; for (int i = 0; i < read - insert ; i++) { bytes2[i] = bytes[i+insert]; } byte[] bytes1 = "000".getBytes(); byte[] bytes3 = new byte[1024]; for (int i = 0; i < bytes1.length + bytes2.length; i++) { if (i < bytes1.length){ bytes3[i] = bytes1[i]; }else { bytes3[i] = bytes2[i - bytes1.length]; } } int len ; if ((len = bytes3.length) != -1){ randomAccessFileOutput.seek(insert); randomAccessFileOutput.write(bytes3,0,len); } randomAccessFileOutput.close(); randomAccessFileInput.close(); } /** * 插入 * @throws IOException */ @Test public void randomAccessWrite4() throws IOException{ File file = new File("text.txt"); RandomAccessFile randomAccessFileInput = new RandomAccessFile(file,"rw"); // 定义插入位置下标(读,写) int insert = 3; int len ; byte[] bytes = new byte[1024]; // 定义一个缓冲 StringBuilder buffer = new StringBuilder((int) file.length()); randomAccessFileInput.seek(insert); while ((len = randomAccessFileInput.read(bytes))!= -1){ buffer.append(new String(bytes, 0, len)); } randomAccessFileInput.seek(insert); randomAccessFileInput.write("www".getBytes()); randomAccessFileInput.write(buffer.toString().getBytes()); } }