待补充
图解:
图1:
图2:
java.io.ObjectOutputStream 类作用:把对象以流的方式写入到文件中实现保存
构造方法:
特有的成员方法:
使用步骤:
示例代码:
package Serializable;
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private 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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package Serializable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//1.创建一个ObajectOutputStream对象,构造方法中传递字节输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\IDea_Project\\Demo01\\person.txt"));
//2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
oos.writeObject(new Person("小黑",12));
//3.释放资源
oos.close();
}
}
ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。
构造方法:
特有的成员方法:
说明:
使用步骤:
示例代码:
package Serializable;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.创建一个ObjectInputStream对象,构造方法中传递字节输出流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("F:\\IDea_Project\\Demo01\\person.txt"));
//2.使用ObjectInputStream对象中的方法readObject读取保存对象的文件
Person person = (Person)oos.readObject();
//3.释放资源
oos.close();
//4.使用
System.out.println(person);
System.out.println(person.getName()+person.getAge());
}
}
当我们把上述示例代码中的age设置为static变量:
package Serializable;
import java.io.Serializable;
public class Person implements Serializable {
private String name;
public static int age;
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package Serializable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//1.创建一个ObajectOutputStream对象,构造方法中传递字节输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\IDea_Project\\Demo01\\person01.txt"));
//2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
Person person =new Person("小黑",12);
oos.writeObject(person);
System.out.println("写入成功,姓名:"+person.getName()+"\t年龄:"+Person.age);
//3.释放资源
oos.close();
}
}
package Serializable;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//1.创建一个ObjectInputStream对象,构造方法中传递字节输出流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("F:\\IDea_Project\\Demo01\\person01.txt"));
//2.使用ObjectInputStream对象中的方法readObject读取保存对象的文件
Person person = (Person)oos.readObject();
//3.释放资源
oos.close();
//4.使用
System.out.println(person);
System.out.println(person.getName()+Person.age);
}
}
把age用transient来修饰
序列化:
反序列化:
总结:
当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操
作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:
Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的,若类的实例变量做了修改,serialVersionUID可能发生变化,故建议,显式声明
图解:
需求:
代码:
package Serializable;
import java.io.*;
import java.util.ArrayList;
public class ListDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList list = new ArrayList<>();
list.add(new Person("大黑",19));
list.add(new Person("小黑",12));
list.add(new Person("大白",13));
list.add(new Person("小白",8));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\IDea_Project\\Demo01\\list.txt"));
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\IDea_Project\\Demo01\\list.txt"));
ArrayList list2 = (ArrayList)ois.readObject();
for(Person person : list2){
System.out.println(person);
}
oos.close();
ois.close();
}
}
待补充
构造函数:
创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式:
如果模式为只读r,则不会创建文件,而是会读取一个已经存在的文件,如果读取的文件不存在则会出现异常,
如果模式为rw读写,如果文件不存在则会去创建文件,如果存在则不会创建文件,会对原有文件内容从头覆盖,能覆盖多少算多少
示例代码1:
package RandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) {
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try{
raf1 = new RandomAccessFile(new File("list.txt"),"r");
raf2 = new RandomAccessFile(new File("list1.txt"),"rw");
byte[] buffer = new byte[1024];
int len;
while((len = raf1.read(buffer)) != -1){
raf2.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(raf1 != null){
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(raf2 != null){
try {
raf2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例代码2:
package RandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("list1.txt"),"rw");
raf.write("abcdefgh".getBytes());
raf.close();
}
}
示例代码3:
从第4个字符后开始覆盖
package RandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("list1.txt"),"rw");
//将指针移动到第4个位置
raf.seek(3);
raf.write("xyz".getBytes());
raf.close();
}
}
示例4:
使用RandomAccessFile实现插入的效果
方式1:
package RandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("list1.txt"),"rw");
//将指针移动到第4个位置
raf.seek(3);
//保存指针指向的第4个位置及以后的数据
//此处如果使用String,我们每次都会在它上面追加,创建新的String,效率差,而StringBuilder底层是数组,直接一次性创建好,效率高一点
//创建一个StringBuilder保存位置后的所有数据,传入文件的长度,提高了效率,不用再次扩容
StringBuilder stringBuilder = new StringBuilder((int) new File("list1.txt").length());
byte[] buffer = new byte[20];
int len;
while ((len = raf.read(buffer))!=-1){
stringBuilder.append(new String(buffer,0,len));
}
//读取完以后,指针就到了最后一个位置,调回指针
raf.seek(3);
raf.write("uvw".getBytes());
//写完之后指针会跟着移动到写入的字符序列的下一个位置
//将stringBuilder写入到文件中
raf.write(stringBuilder.toString().getBytes());
raf.close();
}
}
方式2:
package RandomAccessFile;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("list1.txt"),"rw");
//将指针移动到第4个位置
raf.seek(3);
//保存指针指向的第4个位置及以后的数据
//创建一个ByteArrayOutputStream保存指针后的数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[20];
int len;
while ((len = raf.read(buffer))!=-1){
baos.write(buffer,0,len);
}
//读取完以后,指针就到了最后一个位置,调回指针
raf.seek(3);
raf.write("uvw".getBytes());
//写完之后指针会跟着移动到写入的字符序列的下一个位置
//将stringBuilder写入到文件中
raf.write(baos.toString().getBytes());
raf.close();
}
}
RandomAccessFile与其他流的对比:
应用举例:多线程断点下载