(1)概述:采用字节流读取数据的时候,容易出现乱码问题,这个时候就需要使用字节流而不是字符流(字节流一次只能读取一个字节, 无法确定码表的情况下,转换的过程当中,就会出现乱码,GBK是两个字节进行转换,UTF-8是三个字节进行转换)
(2)常见的编码表
a) ASCII 码表
b) GBK 中国码表(国标)包含有中文信息: 2个字节一组
c) ISO-8859-1 欧洲的码表,在浏览器当中使用得到。 不包含中文
d) Unicode 万国码(所有的国家码表的合集) 3个字节一组
(3)使用场景
a) 字节流
在进行文件复制(拷贝)的时候, 建议采用字节流。因为字节流是万能的,能够百分百的复制。(硬盘 —> 内存 —> 硬盘)
b) 字符流
如果数据是 单独的从内存到硬盘,或者是 从硬盘到内存当中,建议采用字符流。(硬盘 —> 内存 文本文件的数据 —> 展示到控制台当中)
(1)构造方法
方法名 | 备注 |
---|---|
FileWriter(File file) | 给一个File对象构造一个FileWriter对象 |
FileWriter(File file, boolean append) | 给一个File对象构造一个FileWriter对象 |
FileWriter(String fileName) | 构造一个给定文件名的FileWriter对象 |
FileWriter(String fileName, boolean append) | 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据 |
(2)常用方法
方法名 | 备注 |
---|---|
abstract void close() | 关闭流,先刷新 |
abstract void flush() | 刷新流 |
void write(char[] cbuf) | 写入一个字符数组 |
abstract void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(int c) | 写一个字符 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
(3)flush() 方法 和 close() 方法的区别
a) flush() 可以多次使用, 使用完毕之后,还可以调用 write() 方法
b) close() 只能使用一次, 使用完毕之后, 不能继续调用 write()
c) 我们使用了 write() 方法之后,不会直接在 文件当中展示的,需要进行 flush() 刷新 或者 close() 才会展示出来。 并且 close() 方法当中,带有 刷新功能
(1) 构造方法
方法名 | 备注 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File读取 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称 |
(2)常用方法
方法名 | 备注 |
---|---|
int read() | 读一个字符 |
int read(char[] cbuf) | 将字符读入数组 |
(3)案例:(复制文件)
//文件复制案例 - 一次读取一个字符
public class Test02 {
public static void main(String[] args) throws IOException {
String srcPath = "JavaSEDay12\\dir\\原始文件.txt";
String destPath = "JavaSEDay12\\dir\\目标文件1.txt";
// --------
// (1). 创建对象
FileReader fr = new FileReader(srcPath);
FileWriter fw = new FileWriter(destPath);
// (2). 读写数据
int ch;
while ((ch = fr.read()) != -1) {
fw.write(ch);
fw.flush();
}
// (3). 释放资源
fr.close();
fw.close();
}
}
//文件复制案例 - 一次读取一个字符数组
public class Test03 {
public static void main(String[] args) throws IOException {
String srcPath = "JavaSEDay12\\dir\\原始文件.txt";
String destPath = "JavaSEDay12\\dir\\目标文件2.txt";
// --------
// (1). 创建对象
FileReader fr = new FileReader(srcPath);
FileWriter fw = new FileWriter(destPath);
// (2). 读写数据
char[] data = new char[1024];
int len;
while ((len = fr.read(data)) != -1) {
fw.write(data, 0, len);
fw.flush();
}
// (3). 释放资源
fr.close();
fw.close();
}
}
(1)两个常用的字符缓冲流
a) BufferedWriter : 存在特有方法 void newLine() 换行,不区分操作系统。
b) BufferedReader : 存在特有方法 String readLine() 一次读取一行数据。
(2)入门案例
//采用字符缓冲流实现文本文件的复制(一次读取一行)
public class Test01 {
public static void main(String[] args) throws IOException {
String srcPath = "JavaSEDay13\\dir\\原始文件.txt";
String destPath = "JavaSEDay13\\dir\\目标文件3.txt";
// --------
// (1). 创建对象
BufferedReader br = new BufferedReader(new FileReader(srcPath));
BufferedWriter bw = new BufferedWriter(new FileWriter(destPath));
// (2). 读写数据
String line;
//一次读取一行数据,交给 line 判断是否读取到末尾 null
while ((line = br.readLine()) != null) {
bw.write(line); //写入一行字符串
bw.newLine(); //写入换行符 不区分操作系统
bw.flush(); //刷新
}
// (3). 释放资源
br.close();
bw.close();
}
}
(1)概述
(2)入门案例:(将原始文件的(GBK)格式编码,转换成为(UTF-8)编码,进行文件的编码转换)
//采用转换流实现编码转换(GBK-->UTF-8)
public class Test01 {
public static void main(String[] args) throws IOException{
String srcPath = "C:\\Users\\chenhaochuan\\Desktop\\原始gbk文件.txt";
String destPath = "JavaSEDay13\\dir\\目标utf8文件.txt";
String srcCode = "GBK";
String destCode = "UTF-8";
// --------
// (1). 创建对象
//字节流(is、os) --> 字符流(isr、osr) ---> 缓冲流(br、bw)
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(srcPath),srcCode));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath),destCode));
// (2). 读写数据
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
// (3). 释放资源
bw.close();
br.close();
}
}
(1)概述
a) 输出流:
aa) 名称: ObjectOutputStream 对象输出流. 序列化
bb) 本质: class ObjectOutputStream extends OutputStream{ … }
cc) 特有方法: void writeObject(Object)
b) 输入流
aa) 名称: ObjectInputStream 对象输入流. 反序列化
bb) 本质: class ObjectInputStream extends InputStream { … }
cc) 特有方法: Object readObject();
(2)注意事项
a) java.io.NotSerializableException:没有实现接口, 我们序列化的对象所在的类, 没有去实现 java.io.Serializable 接口。Serializable 接口当中啥也没有,他只是一个标记型接口. 只是标记而已
b) java.io.EOFException:在使用 ObjectInputStream 读取数据的时候,读取到末尾。这个流读取到末尾的时候,返回的结果不是 -1 也不是 null 而是一个异常,这个异常的名称叫做 EOFException。
c) java.io.InvalidClassException:我们写对象 writeObject() 之后,对原始的 类文件进行修改,导致 下次读取 readObject() 的时候,版本不匹配。识别失败,出现此异常。(定义一个 序列号。 即可。private static final long serialVersionUID = 666666L)
d) 我们将对象, 写入到文件当中的时候, 某个成员变量 不想被序列化(写入文件),可以采用瞬态关键字 transient
(3)案例
//学生类
//A. 添加序列化接口 java.io.Serializable
//B. 添加序列化的ID private static final long serialVersionUID = -6849794470754667710L;
//C. 有些成员变量不想序列化,添加瞬态 transient
public class Student implements Serializable {
private String name;
private int age;
private transient String gender;
//添加序列化ID
private static final long serialVersionUID = 66666;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
// 测试类
//采用对象操作流,一次读写一个对象
public class Test02 {
public static void main(String[] args) throws Exception {
writeData();
//readData();
}
public static void writeData() throws Exception {
String path = "JavaSEDay13\\dir\\序列化文件2.txt";
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("迪丽热巴", 20, "男"));
list.add(new Student("古力娜扎", 23, "男"));
list.add(new Student("马尔扎哈", 88, "女"));
// --------
// (1). 创建对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
// (2). 读写数据
oos.writeObject(list);
// (3). 释放资源
oos.close();
}
public static void readData() throws IOException, ClassNotFoundException {
String path = "JavaSEDay13\\dir\\序列化文件2.txt";
// --------
// (1). 创建对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
// (2). 读写数据
Object o = ois.readObject();
// (3). 释放资源
ois.close();
// --------
ArrayList<Student> list = (ArrayList<Student>) o;
list.forEach(stu -> System.out.println(stu));
}
}