1.File类的使用
- File类的一个实例对应着磁盘上的文件或文件目录。
- (必须熟悉)File的实例化(新建一个对象),常用的方法
- File类中只有新建,删除,获取路径等方法,不包含读写文件的方法,此时需要使用使用下面说的IO流
- IO流的概述
-
IO流的分类(按不同方式有不同的分类,比如下面)
-
- (按)流向(分类):输入流,输出流
-
- (按)数据处理单位(分类): 字节流,字符流
-
- (按)流的角色(分类):节点流,处理流
-
IO的四个抽象基类:InputStream\OutputStream\Reader\Writer(实际中具体使用的都是这四个基类的子类)
- 节点流之:文件流(上面那四个抽象基类前面加File关键字)
FileInputStream \ FileOutputStream \ FileReader \ FileWriter
其中FileInputStream \ FileOutputStream可处理jpeg文件
FileReader \ FileWriter主要处理txt文件
(步骤)读/写数据的过程如下:
- 步骤1:创建File类的对象,作为读取或写出数据的端点
- 步骤2:创建相关的流的对象(并且将File对象作为参数传进去,读的时候必须真实存在,写的时候File对象其实可以不存在,系统会帮着创建)
- 步骤3:读取/写出数据的过程
- 步骤4:关闭流资源
- 处理流之一:缓冲流(上面那四个抽象基类前面加Buffered关键字)
- BufferedInputStream \ BufferedOutputStream \ BufferedReader \ BufferedWriter
- 作用:实现更高效的读写数据的操作
- 处理流之二:转换流(上面那四个抽象基两两拼接)
-
层次1:熟悉转换流的使用
InputStreamReader输入型的字节流转化成输出型的字符流
OutputStreamWriter输入型的字符流转化成输出型的字节流
回忆下图
-
层次2:(重点需要掌握)字符的编码和解码的过程,常用的字符集
-
- 解决相关的问题: 读写字符出现乱码?本质原因为:使用的解码集和编码集不一致。
- 处理流之三:对象流(Object加四个抽象基类前两个Stream流)
-
层次1:需要熟悉对象流的使用
-
- ObjectInputStream:反序列化需要使用的API(再用这个从文件里解密出来)
-
- ObjectOutputStream:序列化时候需要使用的API(先用这个写到文件里)
-
层次2:对象的序列化机制
-
- 使用场景:不同的进程之间通信,客户端(或浏览器端)与服务器端传输数据
-
- 自定义类要想实现序列化机制需要满足的要求和注意点。
注意三个点
implements Serializable 实现Serializable接口
serialVersionUID 必须要自定义一个。
static int age; //如果定义为static,静态的,后续无法正常序列化,反序列化会得到null。
transient//如果定义为瞬态的,后续无法正常序列化,反序列化会得到null。
快速举例自定义的Person类
import java.io.Serializable;
/*
* 为什么要写implements Serializable?
* 如果不写,会出现错误:java.io.NotSerializableException: IOTest.Person
* 这个错误表示你尝试序列化一个类(在这个例子中是 IOTest.Person 类),
* 但是这个类没有实现 java.io.Serializable 接口。
* 在Java中,要序列化一个对象,该对象的类必须实现 Serializable 接口,
* 否则当你尝试将该对象写入到输出流(如 ObjectOutputStream)时,就会抛出 NotSerializableException 异常。
*
* 这类接口,就叫标识接口
* */
public class Person implements Serializable { //Serializable属于一个标识接口
static final long serialVersionUID = 676600868485450L;
// 上面的serialVersionUID可以随便写个数字,这个编码类似密码一样,注意一定要自己定义。
// 如果自己不定义,系统会在后台帮你默认定义一个serialVersionUID编码,用于序列化+反序列化。
// 这样很危险,因为一旦自定义类的代码被改写,系统就会重新生成一个新的serialVersionUID编码
// 就会造成序列化用着一个“密码”,反序列化用着一个新的“密码”,运行起来就会直接报错。
String name;
static int age; //定义为static,静态的,无法正常序列化,等到反序列化则输出为null
transient long id; //定义为transient,瞬态的,无法正常序列化,等到反序列化则输出为null
Account acct ;
public Person() {
}
public Person(String name, int age, long id) {
this.name = name;
this.age = age;
this.id = id;
}
public Person(String name, int age, long id, Account acct) {
this.name = name;
this.age = age;
this.id = id;
this.acct = acct;
}
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 long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
static class Account implements Serializable {
double balance;
static final long serialVersionUID = 6766005450L;
public Account(double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"balance=" + balance +
'}';
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
", acct=" + acct +
'}';
}
}
使用时,调用Person类并构建对象,并赋值。 使用p2再解码解码出来。
Person p1 = new Person("Ella",6, 60123);
oos1.writeObject(p1);
oos1.flush();
Person p2 = (Person) ois1.readObject();
System.out.println(p2);
ois1.close();
- 其他流的使用
- 了解:数据流 DataInputStream DataOutputStream
- 了解:标准的输入流 System.in 标准的输出流 System.out
- 了解:打印流:PrintStream PrintWriter
- 安装第三方jar包的方法