1. 序列化:
- 概念说明:
将Java对象的数据信息,属性信息写入文件,持久化的到硬盘的操作被称为序列化
对象的序列化和反序列化都通过流实现,这个流被称为对象流
- ObjectOutputStream类
内存中的对象—>存储中的文件、通过网络传输出去:序列化过程
- ObjectInputStream类
将存储中的文件、通过网络接收过来 —>内存中的对象:反序列化过程
序列化的对象需要满足的条件:
- 需要实现接口:Serializable
- 除了当前Person类需要实现Serializable接口之外,还必须保证其内部所属性也必须是可序列化的。(默认情况下,基本数据类型可序列化)
注意:
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
序列化到反序列化过程中不能够修改对象的序列化ID
代码示例:
public class ObjIO {
//序列化
@Test
public void test01() {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"))){
oos.writeObject(new Person("张三",20,"男"));
oos.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
//反序列化
@Test
public void test02() {
try (ObjectInputStream ois = new ObjectInputStream(ObjIO.class.getResourceAsStream("/person.txt"));)
{
Person readObject = (Person) ois.readObject();
System.out.println(readObject);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
class Person implements Serializable{
String name;
Integer age;
transient String sex; //被transient关键字修饰的属性不会被序列化和反序列化
//序列化ID在序列化和反序列化的过程中不可被修改
private static final long serialVersionUID = 1L;
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Person(String name, Integer age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
2. 打印流:
默认的标准输入输出流:
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出
修改默认的输入和输出行为:
System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流。
PrintStream : 打印字节流
PrintWriter : 打印字符流
打印流说明:
提供了一系列重载的print()和println()方法,用于多种数据类型的输出
System.out返回的是PrintStream的实例
代码示例:
@Test
public void test03() {
try {
//初始化PrintStream对象,参数为文件路径
PrintStream ps = new PrintStream("pw.txt");
//重新设置输出流的方向
System.setOut(ps);
//设置后打印的内容将不在控制台显示,而是在pw.txt中显示
System.out.println("你好");
System.out.println("文本");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
3. 任意访问文件流:
RandomAccessFile
可以从文本中读写任意位置的内容
public class RAF {
public static void main(String[] args) throws Exception {
File file = new File("ac.txt");
//任意访问对象类
//r:read读取 w:write写
RandomAccessFile raf = new RandomAccessFile(file, "rw");
//写一个字符进去
raf.write("0123456789".getBytes());//拆成0-9一个个插入文件
System.out.println("文件指针:" + raf.getFilePointer());
//定位到0的索引上
raf.seek(0);
//读取一个字节
int read = raf.read();
System.out.println((char)read);
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
System.out.println((char)raf.read());
//以上读了九个字节,分别对应0-9
System.out.println(raf.read());//-1 表示读取到文件的末尾处
//定位到第101个字节上面
raf.seek(101);
//设置这个文件 的大小
raf.setLength(1000);
raf.writeInt(9);//指针偏移到104
//再写个double
raf.writeDouble(3.14);//指针偏移到112
//再写个long
raf.writeLong(88);//指针偏移到121
//文件指针在哪个索引上?
System.out.println("文件指针:" + raf.getFilePointer());
//要读取9,要定位到101上面
raf.seek(101);
//读取一个int
int readInt = raf.readInt();
System.out.println("readInt:" + readInt);
System.out.println("readDouble:" + raf.readDouble());
System.out.println("readLong:" + raf.readLong());
}
}
运行结果: