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,静态的,无法正常序列化,等到反序列化则输出为nulltransient long id; //定义为transient,瞬态的,无法正常序列化,等到反序列化则输出为nullAccount 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;}@Overridepublic String toString() {return "Account{" +"balance=" + balance +'}';}}@Overridepublic 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包的方法