Java学习Day12------字符流、字符缓冲流、转换流、对象操作流程

字符流、字符缓冲流、转换流、对象操作流程

  • 字符流
    • FileWriter
    • FileReader
  • 字符缓冲流
  • 转换流
  • 对象操作流

字符流

(1)概述:采用字节流读取数据的时候,容易出现乱码问题,这个时候就需要使用字节流而不是字符流(字节流一次只能读取一个字节, 无法确定码表的情况下,转换的过程当中,就会出现乱码,GBK是两个字节进行转换,UTF-8是三个字节进行转换)
(2)常见的编码表
  a) ASCII 码表
  b) GBK 中国码表(国标)包含有中文信息: 2个字节一组
  c) ISO-8859-1 欧洲的码表,在浏览器当中使用得到。 不包含中文
  d) Unicode 万国码(所有的国家码表的合集) 3个字节一组

(3)使用场景
  a) 字节流
    在进行文件复制(拷贝)的时候, 建议采用字节流。因为字节流是万能的,能够百分百的复制。(硬盘 —> 内存 —> 硬盘)
  b) 字符流
    如果数据是 单独的从内存到硬盘,或者是 从硬盘到内存当中,建议采用字符流。(硬盘 —> 内存 文本文件的数据 —> 展示到控制台当中)

FileWriter

(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() 方法当中,带有 刷新功能

FileReader

(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)概述
Java学习Day12------字符流、字符缓冲流、转换流、对象操作流程_第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));
    }
}

你可能感兴趣的:(JavaSE学习,java)