字符流


3.字符流

3.1.为什么出现字符流

由于字节流操作中文不是很方便,所以Java就提供了字符流

  • 字符流 = 字节流 + 编码表
  • 用字节流复制文本文件时,文本文件也会由中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文。
  • 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

3.2编码表

基础知识:

  • 计算机中存储的信息都是用二进制表示的;屏幕上看到的字符都是二进制数转换而来。
  • 按照某种规则将字符存储到计算机中叫编码;反之称为解码。
    • 注:按照A规则编码必须按照A规则解码,否则会乱码。
  • 字符编码:就是一套自然语言的字符与二进制数之间的对应规则(A,65)

字符集

  • 是一个系统支持所有字符的集合,
  • 包括各国的文字,标点符号,图形符号,数字等
  • 为了准确存储和识别各种字符集符号,就需要进行字符编码,
  • 一套字符集编码必然有一套字符编码。
  • 常见的有:ASCII字符集、GBXXX、Unicode字符集等

3.3字符串中的编码解码问题

package com.guoba.day1222.zifu;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/*
        UnsupportedEncodingException:不支持字符编码异常
 */
public class Demo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "中国";
        //byte[] bytes = s.getBytes("UTF-8");//[-28, -72, -83, -27, -101, -67]
        //byte[] bytes = s.getBytes("GBK");//[-42, -48, -71, -6]
        byte[] bytes = s.getBytes();

//        String ss = new String(bytes,"GBK");//涓浗
//        System.out.println(ss);
        String sss = new String(bytes,"utf-8");//中国
        System.out.println(sss);
        //System.out.println(Arrays.toString(bytes));

    }
}

3.4字符流中的编码解码问题

字符流抽象基类

  • Reader: 字符输入流的抽象类

    • InputStreamReader:从字节流到字符流的桥梁

      • 读取字节,并使用指定的编码将其解码为字符
      • 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台默认的字符集
  • Writer:字符输出流的抽象类

    • OutputStreamWriter:从字符流到字节流的桥梁
      • 使用指定的编码将写入的字符编码为字节
      • 使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台默认的字符集

3.5字符流写数据的5种方式

3.6字符流读数据的两种方式

案例:复制Java文件改进版

3.7 字符缓冲流

字符缓冲流:

  • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小,默认值大小,默认值足够大,可用于大多数用途
  • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小,默认值足够大,可以用于大多数用途

构造方法:

  • BufferedWriter(Writer out)
  • BufferedReader(Rerader in)
package com.guoba.day1223;

import java.io.*;

public class Demo01 {
    public static void main(String[] args) throws IOException {
//        FileWriter fw = new FileWriter("基础语法\\fw.txt");
//        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\fw.txt"));
//        bw.write("hello\r\n");
//        bw.write("world\r\n");
//        bw.write("ccccccccccccc\r\n");
//
//        //bw.flush();
//
//        bw.close();
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\\\fw.txt"));
//        //一次读取一个字符数据
//        int by;
//        while ((by=br.read())!= -1){
//            System.out.print((char)by);
//        }
        //一次读取一个字符流数组数据
        int len;
        char[] chars =new char[1024];
        while ((len=br.read(chars))!= -1){
            System.out.print(new String(chars,0,len));
        }
    }
}

"D:\Program Files\Java\jdk1.8.0_202\bin\java.exe" "...
hello
world
ccccccccccccc

Process finished with exit code 0

案例:字符缓冲流创建Java文件

package com.guoba.day1223;

import java.io.*;

/*
    字符缓冲流复制Java文件
        思路:
            1.根据数据源创建字符缓冲输入流对象
            2.根据目标地址创建字符缓冲输出流对象
            3.复制文件(两种方式)
            4.关闭资源
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\Demo01.java"));
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\src\\com\\guoba\\day1223\\Demo01.java"));
//        //一次一个字符
//        int ch;
//        while ((ch=br.read())!= -1){
//            bw.write(ch);
//        }
        //一次一个字符数组
        char[] chars = new char[1024];
        int len;
        while ((len=br.read(chars))!= -1){
            bw.write(chars,0,len);
        }
        //关闭资源
        bw.close();
        br.close();

    }
}

3.8字符缓冲流的特有功能

package com.guoba.day1223;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\ccccc.txt"));

        for (int i = 0; i <10 ; i++) {
            bw.write("ccccccccc"+i);
            bw.newLine();//换行
            bw.flush();//刷新流
        }
        bw.close();
    }
}

package com.guoba.day1223;

import java.io.*;

public class Demo03 {
    public static void main(String[] args) throws IOException {
//        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\ccccc.txt"));
//
////        for (int i = 0; i <10 ; i++) {
////            bw.write("ccccccccc"+i);
////            bw.newLine();//换行
////            bw.flush();//刷新流
////        }
//        bw.close();
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\\\ccccc.txt"));
//        String line = br.readLine();//读一行
//        System.out.println(line);
        String line;
        while ((line=br.readLine())!=null){
            System.out.print(line+"\n");
        }
        br.close();
    }
}

字符缓冲流特有功能复制文件

package com.guoba.day1223;

import java.io.*;

public class Demo04 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\ccccc.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\copy.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        bw.close();
        br.close();
    }
}

3.9 IO流小结




案例:集合到文件

需求:把ArrayList集合中的字符串数据写入到文本文件。

要求:每一个字符串元素作为文件中的一行数据

package com.guoba.day1223;

import java.io.*;
import java.util.ArrayList;

public class Demo05 {
    public static void main(String[] args) throws IOException {
        ArrayList arrayList = new ArrayList<>();
        arrayList.add("张三");
        arrayList.add("李四");
        arrayList.add("王五");
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\集合到文件.txt"));
        for (String s: arrayList){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

案例:文件到集合

package com.guoba.day1223;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo06 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\集合到文件.txt"));
        ArrayList al = new ArrayList<>();
        String line;
        while ((line = br.readLine())!= null){
            al.add(line);
        }

        br.close();
        for (String s : al){
            System.out.println(s);
        }
    }
}

案例:点名器

package com.guoba.day1223;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
/*
        随机点名
 */
public class Demo07 {
    public static void main(String[] args) throws IOException {
        ArrayList arrayList = new ArrayList<>();
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\集合到文件.txt"));
        String line;
        while ((line = br.readLine())!= null){
            arrayList.add(line);
        }
        br.close();

        Random r = new Random();
        int index = r.nextInt(arrayList.size());
        String name = arrayList.get(index);
        System.out.println("幸运者是:"+ name);
    }

}

案例:集合到文件(改进版)

package com.guoba.day1223;

import java.io.*;
import java.util.ArrayList;

/*
        1.创建集合
        2.创建学生对象
        3.把学生添加到集合
        4.创建字符缓冲输出流对象
        5.遍历集合,得到每个学生对象
        6.把学生对象的数据拿到且拼接为指定格式的字符表
        7.调用字符缓冲流对象的方法写数据
        8.关闭资源
 */
public class Demo08 {
    public static void main(String[] args) throws IOException {
        ArrayList arrayList = new ArrayList<>();
        Student student1 = new Student(01,"班尼特",18,"男","蒙德");
        Student student2 = new Student(02,"重云",18,"女","璃月");
        Student student3 = new Student(03,"托马",19,"男","稻妻");
        arrayList.add(student1);
        arrayList.add(student2);
        arrayList.add(student3);
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\TiWaTe.txt"));
        for (Student s : arrayList){
            StringBuilder sb = new StringBuilder();
            sb.append(s.getId()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getSex()).append(",").append(s.getAddress());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

package com.guoba.day1223;

public class Student {
    private int id;
    private int age;
    private String name;
    private String sex;
    private String address;

    public Student() {
    }

    public Student(int id, String name, int age, String sex, String address) {
        this.id = id;
        this.age = age;
        this.name = name;
        this.sex = sex;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

案例:文件到集合(改进版)

package com.guoba.day1223;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo09 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("基础语法\\TiWaTe.txt"));
        ArrayList arrayList = new ArrayList<>();
        String line;
        //从文件获取存入集合
        while ((line = br.readLine())!= null){
            String[] strarr = line.split(",");
            Student s = new Student();
            s.setId(Integer.parseInt(strarr[0]));
            s.setName(strarr[1]);
            s.setAge(Integer.parseInt(strarr[2]));
            s.setSex(strarr[3]);
            s.setAddress(strarr[4]);
            arrayList.add(s);
        }
        br.close();
        //遍历集合
        for (Student s :arrayList){
            System.out.println(s.getId()+","+s.getName()+","+s.getAge()+","+s.getSex()+","+s.getAddress());
        }
    }
}

集合到文件数据排序改进版

package com.guoba.day1223;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Demo10 {
    public static void main(String[] args) throws IOException {
        TreeSet ts = new TreeSet(new Comparator() {
            @Override
            public int compare(Student s1, Student s2) {
                int num1 = s2.getSum() - s1.getSum();
                int num2 = num1 == 0 ? s1.getChinese() - s2.getChinese() : num1;
                int num3 = num1 == 0 ? s1.getMath() - s2.getMath() : num1;
                int num4 = num1 == 0 ? s1.getMath() - s2.getMath() : num1;
                return num4;
            }
        });

        for (int i = 0; i < 5; i++) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入第" + (i + 1) + "个学生信息:");
            System.out.println("姓名:");
            String name = scanner.nextLine();
            System.out.println("语文:");
            int chinese = scanner.nextInt();
            System.out.println("数学:");
            int math = scanner.nextInt();
            System.out.println("英语:");
            int eglish = scanner.nextInt();

            Student s = new Student();
            s.setChinese(chinese);
            s.setMath(math);
            s.setEglish(eglish);
            s.setName(name);

            ts.add(s);
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter("基础语法\\成绩.txt"));
        for (Student s : ts) {
            StringBuilder sb = new StringBuilder();
            sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEglish()).append(",").append(s.getSum());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

案例:复制单极文件夹

package com.guoba.day1223;

import java.io.*;

public class Demo11 {
    public static void main(String[] args) throws IOException{
        //创建数据源目录文件对象
        File srcFolder = new File("E:\\2021Study\\test");
        //获取数据源目录File对象的名称
        String srcFolderName = srcFolder.getName();
        //创建目的地文件对象
        File destFolder = new File("基础语法",srcFolderName);
        //判断目的地目录对应文件是否存在
        if (!destFolder.exists()){
            destFolder.mkdir();
        }
        //获取数据源目录下所有文件的数组
        File[] listFiles = srcFolder.listFiles();
        //遍历得到每一个对象
        for (File srcFile: listFiles){
            String srcFilename = srcFile.getName();
            File destfile = new File(destFolder, srcFilename);
            copyFile(srcFile,destfile);
        }
    }
    private static void copyFile(File srcFile,File destFile)throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read())!= -1){
            bos.write(bys,0,len);
        }
        bos.close();
        bis.close();
    }

}

案例:复制多级文件夹

package com.guoba.day1223;

import java.io.File;
import java.io.IOException;

import static com.sun.deploy.cache.Cache.copyFile;

public class Demo12 {
    public static void main(String[] args) throws IOException {
        File srcFile = new File("E:\\2021Study\\test");//数据源文件对象
        File destFile = new File("F:\\");//目的地文件对象
        copyFolder(srcFile,destFile);//复制文件夹
    }
    //复制文件夹

    private static void copyFolder(File srcFile, File destFile) throws IOException {
        //判断数据源文件是否是目录
        if (srcFile.isDirectory()){
            //在目的地创建和数据源文件名称一样的目录
            String srcFileName = srcFile.getName();
            //使用得到的名称在目的地址创建文件夹
            File newFolder = new File(destFile,srcFileName);
            //判断文件是否存在
            if (!newFolder.exists()){
                //不存在则创建
                newFolder.mkdir();
            }
            //获取数据源文件下所有文件或目录的文件数组
            File[] listFiles = srcFile.listFiles();
            //遍历
            for (File file :listFiles){
                copyFolder(file,newFolder);
            }
        }else {
            //不是文件夹则说明是文件,直接用字节缓冲流复制文件
            File newFile = new File(destFile,srcFile.getName());
            copyFile(srcFile,newFile);
        }
    }
}

案例:复制文件的异常处理

try/catch/finally