对RandomAccessFile、序列化与反序列化的学习

一.RandomAccessFile

  1. 概要 :通过查看API发现RandomAccessFile是Object类的子类,说明它不是一个流,但它融合了InputStream和OutputStream的功能,支持对文件的随机访问读取和写入
  2. public RandomAccessFile(String name,String mode):第一个参数是文件路径,也可以是文件(只是参数变成了 File file,Sting mode),第二个参数是操作文件的模式,最常见的模式为"rw",这种既可以读数据也可以写数据
package IODemo.RandomAccessFileDemo;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class TestOne {

  public static RandomAccessFile raf=null;
   public static void main(String[] args) {
      File file = new File("C:\\Users\\86159\\Desktop\\untitled\\src\\IODemo\\RandomAccessFileDemo\\nnn.txt");
       try {
           write2(file);
           read2(file);
           parseDemo();   //倒置输出功能
       } catch (IOException e) {
           e.printStackTrace();
       }

   }

   private static void read2(File file) throws IOException {
       raf=new RandomAccessFile(file,"rw");
       int i=raf.readInt();
       System.out.println(i);
       //该文件指针能通过gewFilePointer方法获取,并通过seek()方法可设置指针位置
       System.out.println("目前文件指针位置:"+raf.getFilePointer());
       char ch=raf.readChar();
       System.out.println(ch);
       String str=raf.readLine();
       System.out.println(str);


   }

   private static void write2(File file) throws IOException {
        raf=new RandomAccessFile(file,"rw");
       raf.writeInt(100);
       raf.write('d');
       raf.write("China".getBytes());
        raf.close();
   }

   public static void parseDemo() throws IOException {  //RandomAccessFile                                                                                      
                                                      //的倒置方法
       long lon=raf.length();     //我也是想看一下有没有长度方法的,结果是有的
       while(0!=lon--){
           raf.seek(lon);
           char ch= (char) raf.read();
           System.out.print(ch+"");
       }

   }
}

二.序列化与反序列化

  1. 序列化对象: ObjectOutputStream,写数据,把对象按流一样写进去,但该对象一定要实现Serializable接口

  2. 反序列化:ObjectInpuStream ,读数据,把流按对象一样读出来

  3. 感觉就像一种版本的问题

  4. Serializable接口是一个空接口,什么都没有,对这种接口我们把它称为标记接口

//这是测试类
package IODemo.SerializableDemo;

import java.io.*;

public class TestOne {
    public static void main(String[] args) {
        try {
            write2();
            read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void read() throws IOException {
        //创建反序列流对象
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("C:\\Users\\86159\\Desktop\\untitled\\src\\IODemo\\SerializableDemo\\ttt.txt"));
        Object obj=null;
        try {
        //还原对象,反序列化
             obj=ois.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        ois.close();

        System.out.println(obj);
    }

    private static void write2() throws IOException {
        //创建序列流对象
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("C:\\Users\\86159\\Desktop\\untitled\\src\\IODemo\\SerializableDemo\\ttt.txt"));
        //创建对象
        Person p=new Person("zhuyingtai",19);
        oos.writeObject(p);
        //释放资源
        oos.close();
    }
}
------------------------------------------------------------------------

//这是实现序列化对象

package IODemo.SerializableDemo;

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    //private int age;  //一旦Person代码有所改变,那么它的Serializable版本就会有所改变,这就是将对象变成流时遇到的问题,一般来说这样就会使read时发生异常
    int age;
    public Person(){
    }

    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString(){
        StringBuffer sb=new StringBuffer();
        sb.append("Person [ name="+name+"age= "+age+"  ]");
        return sb.toString();
    }
}

当我们将Person类age改为private类型时,Person的class文件发生改变,那么如果我们再把main中的write2()关闭,那么再read的时候将会发生如下异常:

java.io.InvalidClassException: IODemo.SerializableDemo.Person; local class incompatible: stream classdesc serialVersionUID = -6650550249234234848, local class serialVersionUID = -1080759768996651211
  at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
  at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
  at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
  at IODemo.SerializableDemo.TestOne.read(TestOne.java:21)
  at IODemo.SerializableDemo.TestOne.main(TestOne.java:9)

为什么呢,再网上检索之后,我了解到每次Java文件受到更改其verson值就会改变,而在读文件时会和class文件的verson值进行匹配,所以就会发生异常
举个例子:
开始的时候:
Person__verson__1.2
write___ttt.txt__1.2
read___ttt.txt__1.2

更改后:
Person_verson_1.3
write_ttt.txt_1.2
read_ttt.txt_1.3

解决方法:在Person类里加上
private static final long serialVersionUID= -6650550249234234848l;加粗部分为以前的version的Id

主要参考1
主要参考2
以上便是近期对序列化和反序列化的学习与理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值