黑马程序员全套Java教程_Java基础教程_IO流之字符流(三十二)

3.1 为什么会出现字符流

  • 由于字节流操作中文不是特别的方便,所以Java就提供字符流。字符流 = 字节流 + 编码表
  • 用字节流复制中文时,文本文件也会有中文,但最终也复制成功了,原因是最终底层操作会自动进行字节拼接成中文,底层识别成中文的方法:存储汉字的时候,无论选择哪种编码存储,第一个字节都是负数。
    public static void main(String[] args) throws IOException {
        //FileInputStream fis = new FileInputStream("a.txt");
        //
        //int by;
        //while ((by = fis.read()) != -1){
        //    System.out.println(by);
        //}
        //
        //fis.close();

        String s = "abc";
        byte[] bys = s.getBytes();
        System.out.println(Arrays.toString(bys));//[97, 98, 99]

        String s2= "中国";
        byte[] bys2 = s2.getBytes();
        System.out.println(Arrays.toString(bys2));//[-28, -72, -83, -27, -101, -67]
        byte[] bys3 = s2.getBytes("UTF-8");
        System.out.println(Arrays.toString(bys3));//[-28, -72, -83, -27, -101, -67]
        byte[] bys4 = s2.getBytes("GBK");
        System.out.println(Arrays.toString(bys4));//[-42, -48, -71, -6]
    }

3.2 编码表

  • 基础知识:
    (1)计算机中存储的信息都是用二进制数表示的,我们在屏幕上看到的英文、汉字等字符都是二进制数转换之后的结果;
    (2)按照某种规则,将字符存储到计算机中,称为编码;反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。如果按照A编码存储,必须按照A编码解析,这样才能显示正确的文本符号,否则就会出现乱码现象。字符编码是一套自然语言的字符与二进制数之间的对应规则(A,65)。
  • 字符集:
    (1)是一个系统支持的所有字符的集合,包括个国家文字、标点符号、图形符号、数字等;
    (2)计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见的字符集有ASCII字符集、GBXXX字符集、Unicode字符集等。
  • ASCII字符集:
    (1)ASCII(American Standard Code for Informatica Interchange,美国信息交换标准代码):是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号);
    (2)基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
  • GBKXXX字符集:
    (1)GB2312:简体中文码表。码表中小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个汉字,此外数学符号、罗马希腊的字母、日文的假名等都编进去了,连在ASCII里本来就有的数字、标点、字母都通通重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在127号以下的就叫“半角”字符了;
    (2)GBK:最常用的中文编码表。是在GB2312标准基础上的拓展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等;
    (3)GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
  • Unicode字符集:
    (1)为表示任意语言的任意字符而设计,是业界的一种标准,也称统一码、标准万国码。他最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方式,UTF-8、UTF-16和UTF32.最常用的是UTF-8编码。
    (2)UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或者传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。他使用一至四个自己为每个字符编码。编码规则:
    a、128个US-ASCII字符,只需一个字节编码;
    b、拉丁文等字符,需要两个字节编码;
    c、大部分常用字(含中文),使用三个字节编码;
    d、其他极少使用的Unicode辅助字符,使用四字节编码。
  • 强调:采用何种规则编码,就要采用对应规则解码,否则就会出现乱码。

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

  • 编码:
    (1)byte[] getBytes():使用平台(如IDEA平台)的默认字符集将该String字符串编码为一系列字节,将结果存储到新的字节数组中;
    (2)byte[] getBytes(String charsetName):使用指定的字符集将该String字符串编码为一系列字节,将结果存储到新的字节数组中。
  • 解码:
    (1)String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String字符串;
    (2)String(byte[] bytes, String charsetName):通过指定的字符集编码指定的字节数组来构造新的String字符串。
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s2= "中国";

        byte[] bys2 = s2.getBytes();
        System.out.println(Arrays.toString(bys2));//[-28, -72, -83, -27, -101, -67]
        String str2 = new String(bys2);
        System.out.println(str2);//中国

        byte[] bys3 = s2.getBytes("UTF-8");
        System.out.println(Arrays.toString(bys3));//[-28, -72, -83, -27, -101, -67]
        String str3 = new String(bys3,"UTF-8");
        System.out.println(str3);//中国

        byte[] bys4 = s2.getBytes("GBK");
        System.out.println(Arrays.toString(bys4));//[-42, -48, -71, -6]
        String str4 = new String(bys4,"GBK");
        System.out.println(str4);//中国
        String str5 = new String(bys4,"UTF-8");
        System.out.println(str5);//�й�
    }

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

  • 字符流抽象基类:
    (1)Reader:字符输入流的抽象类;
    (2)Writer:字符输出流的抽象类。
  • 字符流中和编码解码问题相关的两个类:
    (1)InputStreamReader;
    (2)OutputStreamWriter。
    public static void main(String[] args) throws IOException {
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"UTF-8");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"GBK");

        osw.write("中国");
        osw.close();

        //InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
        //InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"),"UTF-8");
        InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");
        
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.print((char) ch);
        }

        isr.close();
    }

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

方法名说明
void write(int c)写一个字符
void write(char[] cbuf)写入一个字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写入一个字符串
void write(String str, int off, int len)写入一个字符串的一部分
  • flush()和close()的区别
方法名说明
flush()刷新流,还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));

        osw.write(97);
        osw.write(44);
        //osw.flush();//刷新流,让底层的字节流将数据写入到文件(字符流相对字节流是有缓冲的),如果后面osw.close()了就不需要了,因为close方法帮我们刷新了

        char[] chs = {'1','4','5','6'};
        osw.write(chs);

        //osw.write(chs,1,10);//IndexOutOfBoundsException
        osw.write(chs,1,2);

        osw.write("liubei\r\n");

        osw.write("guanguanyu",4,6);

        osw.close();//先刷新,再关闭流(释放资源)
    }

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

方法名说明
int read()一次读一个字符数据
int read(char[] cbuf)一次读一个字符组数据
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));

        //方法1:一次读取一个数据
        //int ch;
        //while ((ch = isr.read()) != -1) {
        //    System.out.print((char) ch);
        //}

        //方法2:一次读取一个字符数组
        char[] chs = new char[1024];
        int len;
        while ((len = isr.read(chs)) != -1){
            System.out.println(new String(chs,0,len));
        }

        isr.close();
    }

3.7 案例:复制Java文件

  • 需求:把模块目录下的“ConversionStreamDemo.java”复制到模块目录下的“Copy.java”。
  • 思路:
    (1)根据数据源创建字节输入流对象;
    (2)根据目的地创建字节输出流对象;
    (3)读写数据,复制文件;
    (4)释放资源。
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("src\\itheima2\\ConversionStreamDemo.java"));
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Copy.java"));

        //一次读写一个字符数据
        //int ch;
        //while ((ch=isr.read()) != -1){
        //    osw.write(ch);
        //}

        //一次读写一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while ((len=isr.read(chs)) != -1){
            osw.write(chs,0,len);
        }

        isr.close();
        osw.close();
    }

案例:复制Java文件(改进版)

  • 需求:把模块目录下的“ConversionStreamDemo.java”复制到模块目录下的“Copy.java”。
  • 分析:
    (1)转换流的名字比较长(比如InputStreamReader和OutputStreamWriter),而我们常见的操作都是按照本地默认编码实现的,所以为了简化书写,转换流提供了对应的子类;
    (2)FileReader:用于读取字符文件的便捷类,构造方法为FileReader(String fileName);
    (3)FileWriter:用于写入字符文件的便捷类,构造方法为FileWriter(String fileName);
    (4)数据源和目的地的分析:
    a、数据源:ConversionStreamDemo.java -> 读数据 -> Reader(抽象类) -> inputStreamReader -> FileReader;
    b、目的地:Copy.java -> 写数据 -> Writer(抽象类) -> OutputStreamWriter -> FileWriter。
    c、注意:如果在字符流中涉及到编码和解码的问题,我们还是要使用转换流inputStreamReader和OutputStreamWriter。
  • 思路:
    (1)根据数据源创建字节输入流对象;
    (2)根据目的地创建字节输出流对象;
    (3)读写数据,复制文件;
    (4)释放资源。
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("src\\itheima2\\ConversionStreamDemo.java");
        FileWriter fw = new FileWriter("Copy.java");

        //int ch;
        //while ((ch=fr.read()) != -1){
        //    fw.write(ch);
        //}

        char[] chs = new char[1024];
        int len;
        while ((len=fr.read(chs)) != -1){
            fw.write(chs,0,len);
        }

        fr.close();
        fw.close();
    }

3.7 字符缓冲流

  • 字符缓冲流:
    (1)BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接收默认大小。默认值足够大,可用于大多数用途;
    (2)BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。默认值足够大,可用于大多数用途。
  • 构造方法:
    (1)BufferedWriter(Writer out);
    (2)BufferedReader(Reader in)。
    public static void main(String[] args) throws IOException {
    	//BufferedReader和BufferedWriter对象内封装的是一个长度为9192的字符数组
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

        int ch;
        while ((ch = br.read()) != -1){
            bw.write(ch);
        }

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

案例:复制Java文件(字符缓冲流改进版)

  • 需求:把模块目录下的“ConversionStreamDemo.java”复制到模块目录下的“Copy.java”。
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("src\\itheima2\\ConversionStreamDemo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));

        //int ch;
        //while ((ch=br.read()) != -1){
        //    bw.write(ch);
        //}

        char[] chs = new char[1024];
        int len;
        while ((len=br.read(chs)) != -1){
            bw.write(chs,0,len);
        }

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

3.8 字符缓冲流的特有功能

  • BufferedWriter:void newLine(),写一行行分隔符(换行符),行分隔符字符串由系统属性定义。
  • BufferedReader:pubic String readLine(),读一行文字,结果包括行的内容的字符串,不包括任何行终止字符(换行符),如果流的结尾已经到达,则为null
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("b.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

        for (int i = 0; i < 10; i++){
            bw.write("hello" + i);
            //bw.write("\r\n");
            bw.newLine();
            bw.flush();
        }

        String s = new String();
        while ((s = br.readLine()) !=null){
            System.out.println(s);
        }

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

案例:复制Java文件(字符缓冲流特有功能改进版)

  • 需求:把模块目录下的“ConversionStreamDemo.java”复制到模块目录下的“Copy.java”。
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("src\\itheima2\\ConversionStreamDemo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));

        String s;
        while ((s = br.readLine()) != null){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }

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

3.9 IO流小结

  • 字节流:
    在这里插入图片描述

在这里插入图片描述
小结1:字节流可以复制任意文件数据,有4种方式,一般采用字节缓冲流一次写一个字节数组的方式

  • 字符流:在这里插入图片描述
    在这里插入图片描述

小结2:字符流只能复制文本数据,有5种方式,一般采用字符缓冲流的特有功能。

  • (1)字节流(可以读写任意文件数据):
    字节输入流InputStream->文件字节输入流FileInputStream, 字节缓冲流BufferedInputStream(文件字符输入流和文件字符输出流都可以使用一次读取一个字符和一次读取一个字符数组的方法,共计四种读取方式)
    字节输出流OutputStream->文件字节输出流FileOutputStream, 字节缓冲流BufferedOutputStream
    (2)
    字符流(只能复制文本数据):
    字符输入流Reader->(InputStreamReader->FileReader(特殊方法String readLine())), 字符缓冲流BufferedReader
    字符输出流Writer->(OutputStreamWriter->FileWriter(特殊方法void newLine(), void write(String line))),字符缓冲流 BufferedWriter

案例:集合到文件

  • 需求:把ArrayList集合汇总的字符串数据写入到文本文件。要求:每一个字符串作为文件中的一行数据。
  • 思路:
    (1)创建ArrayList集合;
    (2)往集合中存储字符串元素;
    (3)创建字符缓冲输出流对象;
    (4)遍历集合,得到每一个字符串数据;
    (5)调用字符串冲输出流对象的方法写数据;
    (6)释放资源。
    public static void main(String[] args) throws IOException {
        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("liubei");
        arrayList.add("guanyu");
        arrayList.add("zhangfei");

        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));

        for (String s : arrayList){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }

案例:文件到集合

  • 需求:把文本文件中的数据读取到集合中,并遍历集合。要求文件中每一行数据是一个集合元素。
  • 思路:
    (1)创建字符缓冲输入流对象;
    (2)创建ArrayList集合对象;
    (3)调用字符换成输入流对象的方法读数据;
    (4)把读到的字符串数据存储到集合中;
    (5)释放资源;
    (6)遍历集合。
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));

        ArrayList<String> arrayList = new ArrayList<>();

        String line;
        while ((line = br.readLine()) != null){
            arrayList.add(line);
        }

        br.close();

        for (String s : arrayList){
            System.out.println(s);
        }
    }

案例:点名器

  • 需求:有一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。
  • 思路(1-5步同上一案例文件到集合):
    (1)创建字符缓冲输入流对象;
    (2)创建ArrayList集合对象;
    (3)调用字符换成输入流对象的方法读数据;
    (4)把读到的字符串数据存储到集合中;
    (5)释放资源;
    (6)使用Random产生一个随机数,随机数的范围在[0,集合的长度);
    (7)把第6步产生的随机数作为索引到ArrayList集合中获取值;
    (8)把第7步得到的随机数据输出在控制台。
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));

        ArrayList<String> arrayList = new ArrayList<>();

        String line;
        while ((line = br.readLine()) != null){
            arrayList.add(line);
        }

        br.close();

        Random r = new Random();
        int index = r.nextInt(arrayList.size());

        System.out.println(arrayList.get(index));
    }

案例:集合到文件(学生数据版)

  • 需求:把ArrayList集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据。格式:学号,姓名,年龄,居住地。如itheima001,林青霞,30,西安。
  • 思路:
    (1)定义学生类;
    (2)创建ArrayList集合;
    (3)创建学生对象;
    (4)把学生对象添加到集合中;
    (5)创建字符缓冲输出流对象;
    (6)遍历集合,得到每一个学生对象;
    (7)把学生对象的数据拼接成指定格式的字符串;
    (8)调用字符缓冲输出流对象的方法写数据;
    (9)释放资源。
public class Student {
    private String num;
    private String name;
    private int age;
    private String address;

    public Student() {
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "num='" + num + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
    public static void main(String[] args) throws IOException {
        ArrayList<Student> arrayList = new ArrayList<>();

        arrayList.add(new Student("001","刘备",12,"广州"));
        arrayList.add(new Student("002","关羽",22,"上海"));
        arrayList.add(new Student("003","张飞",32,"深圳"));

        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));

        for (Student s : arrayList){
            //bw.write(s.getNum() + "," + s.getName() + "," + s.getAge() + "," + s.getAddress());
            StringBuffer sb = new StringBuffer();
            sb.append(s.getNum()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());
            bw.write(sb.toString());
            //bw.write("\r\n");
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }

案例:文件到集合(学生数据版)

  • 需求:把文本文件中的学生数据读取到集合中。要求:文件中每一行数据是一个学生对象的成员变量值。如itheima001,林青霞,30,西安。
  • 思路:
    (1)定义学生类;
    (2)创建字符缓冲输入流对象;
    (3)创建ArrayList集合对象;
    (4)调用字符缓冲输入流对象的方法读数据;
    (5)把读取到的字符串数据用split()进行分割,得到一个字符串数组;
    (6)创建学生对象;
    (7)把字符串数组中的每一个元素取出来赋值给学生对象对应的成员变量;
    (8)把学会说呢过对象添加到集合;
    (9)释放资源;
    (10)遍历集合。
public class Student {
    private String num;
    private String name;
    private int age;
    private String address;

    public Student() {
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "num='" + num + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
    public static void main(String[] args) throws IOException {
        ArrayList<Student> arrayList = new ArrayList<>();

        BufferedReader br = new BufferedReader(new FileReader("a.txt"));

        String line;
        while ((line = br.readLine()) != null){
            String[] strs = line.split(",");
            arrayList.add(new Student(strs[0],strs[1],Integer.parseInt(strs[2]),strs[3]));
        }

        br.close();

        for (Student s : arrayList){
            System.out.println(s);
        }
    }

案例:集合到文件(学生数据排序版)

  • 需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件。格式:姓名,语文成绩,数学成绩,英语成绩。如:林青霞,98,99,100。
  • 思路:
    (1)定义学生类;
    (2)创建TreeSet集合,通过比较器排序进行排序;
    (3)键盘录入学生数据;
    (4)创建学生对象,把键盘录入的数据对应赋值给学生对象的成员变量;
    (5)把学生对象添加到TreeSet集合;
    (6)创建字符缓冲输出流对象;
    (7)遍历集合,得到每一个学生对象;
    (8)把学生对象的数据拼接成指定格式的字符串;
    (9)调用字符串缓冲输出流对象的方法写数据;
    (10)释放资源。
    public static void main(String[] args) throws IOException {
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getChineseScore() + s1.getEnglishScore() + s1.getMathScore() - (s2.getChineseScore() + s2.getEnglishScore() + s2.getMathScore());
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });

        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < 5; i++) {
            System.out.println("请输入第" + (i + 1) + "个学生的姓名,语文成绩,数学成绩,英语成绩:");
            String str = sc.nextLine();
            String[] strs = str.split(",");
            ts.add(new Student(strs[0], Integer.parseInt(strs[1]), Integer.parseInt(strs[2]), Integer.parseInt(strs[3])));
        }

        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));

        for (Student s : ts) {
            StringBuffer sb = new StringBuffer();
            sb.append(s.getName()).append(",").append(s.getChineseScore()).append(",").append(s.getMathScore()).append(",").append(s.getEnglishScore());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }

案例:复制多级文件夹

  • 需求:把“E:\itcast”这个文件夹复制到模块目录下。
  • 思路:
    (1)创建数据源目录File对象,路径是E:\itcast;
    (2)创建目的地目录File对象,路径名是E:\itcast2;
    (3)获取数据源目录下的所有文件的File数组;
    (4)遍历File数组,得到每一个File对象,判断数据源File是否为目录,是:
    a、在目的地下创建和数据源File名称一样的目录;
    b、把该File作为数据源File对象,新创建的目录作为目的地File对象,递归调用复制文件夹的方法。
    不是:说明是文件(数据源文件如E:\itcast\mn,jpg),直接用字节流复制:
    a、创建目的地文件File对象,路径名是目的地全路径+"\"+mn.jpg组成(E:\itcast\mn.jpg);
    b、复制文件,由于文件不仅仅是文本文件,还有图片,视频等文件,所以采用字节流复制文件。
  • 复制单级文件夹
    public static void main(String[] args) throws IOException {
        //1
        File file = new File("E:\\itcast");

        CopyDir(file);
    }

    public static void CopyDir(File file) throws IOException {
        //2
        String dirname = file.getName();
        //3
        File destFloder = new File(file.getName());
        //4
        if (!destFloder.exists()){
            destFloder.mkdir();
        }
        //5
        File[] listFiles = file.listFiles();
        //6
        for (File srcFile : listFiles){
            //7获取数据源文件File对象的名称
            String srcFileName = srcFile.getName();
            //8创建目的地文件
            File destFile = new File(destFloder, srcFileName);
            //9
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
            //10.1
            //int i;
            //while ((i = bis.read()) != -1){
            //    bos.write(i);
            //}
            //10.2
            byte[] bys = new byte[1024];
            int len;
            while ((len=bis.read(bys))!=-1){
                bos.write(bys,0,len);
            }

            bis.close();
            bos.close();
        }
    }
  • 复制多级文件夹
    public static void main(String[] args) throws IOException {
        //(1)
        File srcDir = new File("E:\\itcast");
        //(2)
        File destDir = new File("E:\\itcast2");

        CopyDir(srcDir,destDir);
    }

    public static void CopyDir(File srcDir,File destDir) throws IOException {
        //(3)
        File[] listFiles = srcDir.listFiles();
        //(4)
        for (File srcFile : listFiles){
            File destFile = new File(destDir.getAbsolutePath()+"\\"+srcFile.getName());
            if (srcFile.isDirectory()){
                //a
                destFile.mkdir();
                //b
                CopyDir(srcFile,destFile);
            }else if (srcFile.isFile()){
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));

                //int i;
                //while ((i=bis.read()) != -1){
                //    bos.write(i);
                //}

                byte[] bys = new byte[1024];
                int len;
                while ((len=bis.read(bys)) != -1){
                    bos.write(bys,0,len);
                }

                bis.close();
                bos.close();
            }
        }
    }

3.10 复制文件的异常处理

  • 抛出处理
    //抛出处理
    private static void method() throws IOException {
        FileReader fr = new FileReader(new File("fr.txt"));
        FileWriter fw = new FileWriter(new File("fw.txt"));

        char[] chs = new char[1024];
        int len;
        while ((len=fr.read(chs)) != -1){
            fw.write(chs,0,len);
        }

        fr.close();
        fw.close();
    }
try{
	可能出现异常的代码;
}catch(异常类名 变量名){
	异常的处理代码;
}finally{
	执行所有清除操作;
}
    private static void method2(){
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader(new File("fr.txt"));
            fw = new FileWriter(new File("fw.txt"));

            char[] chs = new char[1024];
            int len;
            while ((len = fr.read(chs)) != -1) {
                fw.write(chs, 0, len);
            }

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (fw!=null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fw!=null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • JDK7改进方案
try(定义流对象){
	可能出现异常的代码;
}catch(异常类名 变量名){
	异常处理代码;
}
(自动释放资源)
    private static void method3(){
        try(FileReader fr = new FileReader(new File("fr.txt"));
            FileWriter fw = new FileWriter(new File("fw.txt"));){
            char[] chs = new char[1024];
            int len;
            while ((len = fr.read(chs)) != -1) {
                fw.write(chs, 0, len);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
  • JDK9改进方案
定义输入流对象;
定义输出流对象;
try(输入流对象,输出流对象){
	可能出现异常的代码;
}catch(异常类名 变量名){
	异常的处理代码;
}
(自动释放资)
    private static void method4() throws IOException{
        FileReader fr = new FileReader(new File("fr.txt");
        FileWriter fw = new FileWriter(new File("fw.txt");
        try(fr,fw){
            char[] chs = new char[1024];
            int len;
            while ((len = fr.read(chs)) != -1) {
                fw.write(chs, 0, len);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值