一.RandomAccessFile
- 概要 :通过查看API发现RandomAccessFile是Object类的子类,说明它不是一个流,但它融合了InputStream和OutputStream的功能,支持对文件的随机访问读取和写入
- 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+"");
}
}
}
二.序列化与反序列化
-
序列化对象: ObjectOutputStream,写数据,把对象按流一样写进去,但该对象一定要实现Serializable接口
-
反序列化:ObjectInpuStream ,读数据,把流按对象一样读出来
-
感觉就像一种版本的问题
-
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