JAVA009【File,递归,字节流,字符流】

1.文件路径概述

/**
目标:能够辨别相对路径和绝对路径

讲解:
    1. 文件路径的分类
        相对路径
        绝对路径

    2. 绝对路径概述
        以盘符开始的路径,在系统中具有唯一性。
        比如:
            C:/aaa/bbb/a.txt
            D:/aaa/bbb/a.txt

    3. 相对路径概述
        没有以盘符开始,相对于某个位置而言,不具有唯一性。
        比如:E:/aaa/zzz   a.png
        注意:如果在代码中使用的路径是相对路径,则默认相对位置是:当前项目的根目录
            比如:aaa.txt ==> 默认在当前项目的根目录查找该文件
            比如:aaa/bbb/ccc.png ==> 会在项目根目录下先查找aaa文件夹,然后查找bbb文件夹,最后查找ccc.png


小结:
    如何判断文件路径是相对路径还是绝对路径?
        判断是否以盘符开始,是则绝对路径,否则是相对路径:相对当前项目根目录

*/
public class Demo01 {
}


## 2.File类构造方法

```java
package com.itheima._02File类构造方法;

import java.io.File;

/**
    目标:掌握File类常用的构造方法

    讲解:
        1. File类的作用
            文件和目录路径名的抽象表示形式。
            作用:用来操作硬盘上的文件或文件夹,比如获得文件名字,文件大小...

        2. File类常用构造方法
             public File(String pathname)
                根据文件路径字符串创建文件对象
             public File(String parent,String child)
                根据父路径字符串和子类路径字符串创建文件对象
             public File(File parent,String child)
                根据父路径文件对象和子类路径字符串创建文件对象

    小结:
        1. File的作用:用来操作文件或文件夹

        2. File类常用的构造方法
            File(String path)
            File(String parent,String child)
            File(File parent,String child)
 */
public class Demo02 {
    public static void main(String[] args) {
        // 根据文件路径字符串创建文件对象:绝对路径
        File f1 = new File("C:/aaa/a.txt");
        // 根据文件路径字符串创建文件对象:相对路径
        File f2 = new File("a.txt");
        System.out.println(f1);
        System.out.println(f2);
        System.out.println("-------------------");
        // 根据父路径字符串和子类路径字符串创建文件对象
        // 绝对路径
        File f3 = new File("d:/ddd/eee/","a.png");
        System.out.println(f3);
        // 相对路径:ddd/eee/a.png
        File f4 = new File("ddd/eee/","a.png");
        File f5 = new File("ddd/eee/a.png");
        System.out.println(f4);
        System.out.println(f5);
        System.out.println("--------------------");
        // 根据父路径文件对象和子类路径字符串创建文件对象
        File f6 = new File(new File("d:/ddd/eee/"),"a.png");
        System.out.println(f6);
    }
}

3.File常用方法-获取功能

package com.itheima._03File类常用方法._01获取功能;

import java.io.File;

/**
    目标:掌握File类获取文件信息的相关方法

    讲解:
        1. File类与获取文件信息相关的方法
             public String getAbsolutePath() :
                获得文件的绝对路径字符串
             public String getPath() :
                获得文件路径字符串(创建文件对象时指定的路径字符串)
             public String getName() :
                获得文件或文件夹名称
             public long length() :
                获得文件的大小,单位:字节
                如果文件不存在,则返回值为0
                只能获得文件的大小,不能获得文件夹大小
                如果文件对象关联的是文件夹则返回值是一个不确定的值

             public File getParentFile();
                获得父路径文件对象

 */
public class Demo031 {
    public static void main(String[] args) {
        // 创建文件对象
        File f = new File("/Users/pkxing/Documents/aaa.jpg");
        // 获得文件绝对路径字符串
        // /Users/pkxing/Documents/IDEAProject/119期就业班/a.txt
        System.out.println(f.getAbsolutePath());
        // 获得文件路径字符串
        System.out.println(f.getPath());
        // 获得文件或文件夹名称
        System.out.println(f.getName()); // a.txt
        // 获得文件大小
        System.out.println(f.length()); // 736

        // 获得父路径文件对象
        System.out.println(f.getParentFile());

    }
}

4.判断功能

package com.itheima._03File类常用方法._02判断功能;

import java.io.File;

/**
    目标:掌握File类与判断功能相关的方法

    讲解:
        1. File类与判断相关的方法
            boolean exists();
                判断文件或文件夹是否存在,存在返回true,否则false
            boolean isDirectory();
               判断文件对象关联的是否是文件夹,是返回true,否则false
               如果文件或文件夹不存在在返回false
            boolean isFile();
                判断文件对象关联的是否是文件,是返回true,否则false

    小结:
        1. 说出exists()方法作用:判断文件夹或文件是否存在

        2. 说出isDirectory()方法作用:判断是否是文件夹

        3. 说出isFile()方法作用:判断是否是文件

 */
public class Demo032 {
    public static void main(String[] args) {
        // 创建文件对象
        File f = new File("/Users/pkxing/documents/aaaa");
        System.out.println(f.exists()); // true
        System.out.println(f.isDirectory()); // true
        System.out.println(f.isFile()); // false
    }
}

5.创建功能

package com.itheima._03File类常用方法._03创建功能;

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

/**
    目标:能够使用File类提供的方法创建文件和文件夹

    讲解:
        1. File类与创建文件和文件夹相关的方法
            boolean createNewFile()
                创建文件,创建成功返回true,否则false
                如果文件已经存在,则直接返回false,不会创建了
                只能用来创建文件,不能创建文件夹

            boolean mkdir() ==> make directory
                创建单级文件夹,创建成功返回true,否则false
                如果文件夹存在则直接返回false,不会创建了
                只能创建文件夹,不能创建文件

            boolean mkdirs()
                 创建单级或多级文件夹,创建成功返回true,否则false
                 如果文件夹存在则直接返回false,不会创建了
                 只能创建文件夹,不能创建文件

    小结:
        1. 创建普通文件的方法
            boolean createNewFile()

        2. 创建文件夹的方法
            boolean mkdirs()
 */
public class Demo033 {
    public static void main(String[] args) throws IOException {
        // 创建文件对象
        File f = new File("ee");
        // 创建文件
        // System.out.println(f.createNewFile());

        // 创建单级文件夹
        // System.out.println(f.mkdir());

        // 创建多级文件夹
        System.out.println(f.mkdirs());
    }
}

6.删除功能

package com.itheima._03File类常用方法._04删除功能;

import java.io.File;

/**
    目标:能够使用File类提供的方法删除文件或文件夹

    讲解:
        1. File类与删除文件和文件夹相关的方法
            boolean delete()
                删除文件或文件夹:删除成功返回true,否则false
                如果文件不存在,直接返回false
                如果是文件夹则只能删除空文件夹

    小结:
        1. 删除文件和文件夹使用哪个方法
            delete
 */
public class Demo034 {
    public static void main(String[] args) {
        // 创建文件对象
        File f = new File("/Users/pkxing/documents/Java学科");
        // 删除文件
        System.out.println(f.delete());
    }
}

7.遍历功能

package com.itheima._03File类常用方法._05遍历功能;

import java.io.File;
import java.util.stream.Stream;

/**
    目标:能够掌握File目录的遍历

    讲解:
        File类与目录遍历相关的方法
            * File[] listFiles()
                * 获得当前文件夹下的所有文件

    小结:
        1. 说出String[] list()的作用:获得当前文件夹下的所有文件,返回字符串数组

        2. 说出File[] listFiles()的作用:获得当前文件夹下的所有文件,返回文件数组
 */
public class Demo034 {
    public static void main(String[] args) {
        // 创建文件对象:关联文件夹
        File dir = new File("/Users/pkxing/documents/aaa.jpg");
        if (dir.isDirectory()){
            // 获得文件夹下的所有文件
            File[] files = dir.listFiles();
            System.out.println(files);
            // 遍历文件数组
            for (File file : files) {
                System.out.println(file);
            }

            // 遍历输出
            // Consumer接口抽象方法:void accept(T t)
            /*Stream.of(files).forEach(file->{
                System.out.println(file.getName());
            });*/
        }

    }
}

8.File类静态成员变量

package com.itheima._04File类静态成员变量;

import java.io.File;
import java.io.FileReader;

/**
    目标:了解File类两个静态成员变量

    讲解:
        1. File类两个常见的静态成员变量
             static String pathSeparator
                * 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
                * 不同的操作系统有不同路径分隔符
                * MAC或Linux是 :
                * Windows是 ;

             static String separator
                * 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
                * 不同的操作系统有不同名称分隔符
                * MAC或Linux是 /
                * Windows是 \

    小结:
        1. pathSeparator的作用:路径分隔符

        2. separator的作用:名称分隔符
 */
public class Demo04 {
    public static void main(String[] args)throws Exception {
        System.out.println(File.pathSeparator);
        System.out.println(File.separator);


        FileReader fr = new FileReader("day09_课堂代码/a.txt");
        System.out.println(fr.read());
        fr.close();
    }
}

9.递归概述

package com.itheima._05递归概述;

/**
    目标:能够理解递归的概念

    讲解:
        1. 什么是递归
            方法自身调用自身则称为递归

        2. 递归的分类
            间接递归:A方法调用B方法,B方法调用C方法,C方法调用A方法
            直接递归:A方法调用A方法

        3. 递归的注意事项
            * 递归要有出口:结束递归的条件
            * 递归次数不要太多

    小结:
        1. 说出什么是递归
            方法自身调用自身

        2. 说出递归的两个注意事项
            要有结束递归的条件
            递归次数不能太多
 */
// 间接递归演示 : java.lang.StackOverflowError 栈内存溢出错误
public class Demo05 {
    private static int index = 0;
    // A方法调用B方法,B方法调用C方法,C方法调用A方法
    public static void main(String[] args) {
        System.out.println("main..." + index++); // 0
        testA();
        System.out.println("main..." + index++);
    }

    public static void testA(){
        if (index >= 4) return;
        System.out.println("testA..." + index++); // 1
        testB();
        System.out.println("testA..." + index++);
    }

    public static void testB(){
        System.out.println("testB..." + index++); // 2
        testC();
        System.out.println("testB..." + index++);
    }

    public static void testC(){
        System.out.println("testC..." + index++); // 3
        testA();
        System.out.println("testC..." + index++);
    }
}

package com.itheima._05递归概述;


// 直接递归演示 : java.lang.StackOverflowError 栈内存溢出错误
public class Demo06 {
    private static int index = 0;

    public static void main(String[] args) {
        System.out.println("main..." + index++);
        testA();
        System.out.println("main..." + index++);
    }

    public static void testA(){
        if (index >= 4) return;
        System.out.println("testA..." + index++);
        testA();
        System.out.println("testA..." + index++);
    }
}

10.递归练习

package com.itheima._06递归练习;

/**
    需求:使用递归求1到n的和

    讲解:
        1. 使用递归实现功能的步骤:
            1. 定义方法:确定返回值和参数列表
            2. 找递归的规律
            3. 找递归的出口


        2. 分析查找递归规律
            n = 5;
                sum(5) = 1 + 2 + 3 + 4 + 5 = sum(4) + 5;
            n = 4;
                sum(4) = 1 + 2 + 3 + 4 = sum(3) + 4;
            n = 3;
                sum(3) = 1 + 2 + 3 = sum(2) + 3;
            n = 2;
                sum(2) = 1 + 2 = sum(1) + 2
            n = 1;
                sum(1) = 1;
            n > 1:
                sum(n) = sum(n-1) + n;

        3. 画图分析递归执行流程
 */
public class Demo061 {

    public static void main(String[] args) {
        System.out.println(sum(5));
        System.out.println(sum(1));
    }

    // 1. 定义方法:确定返回值和参数列表
    public static int sum(int n){
        if (n == 1) return 1;
        return sum(n-1) + n;
    }
}

package com.itheima._06递归练习;

/**
    需求:使用递归求n!
            n! = 1 * 2 * 3 *...n

    讲解:
        1. 使用递归实现功能的步骤:
            1. 定义方法:确定返回值和参数列表
            2. 找递归的规律
            3. 找递归的出口

        2. 分析查找递归规律
 */
public class Demo062 {

    public static void main(String[] args) {
        System.out.println(jc(5)); // 120
    }

    // 1. 定义方法:确定返回值和参数列表
    public static int jc(int n){
        if (n == 1) return 1;
        return jc(n-1) * n;
    }
}

package com.itheima._06递归练习;

import java.io.File;

/**
    需求:搜索c:\abc目录中的.java文件。

    讲解:
         1. 使用递归实现功能的步骤:
             1. 定义方法:确定返回值和参数列表
             2. 找递归的规律
             3. 找递归的出口

         2. 实现步骤分析
            1. 获得目标文件夹下的所有文件:得到文件数组
            2. 遍历文件数组获得每个文件对象
            3. 判断是否是文件,判断是java文件
            4. 如果是文件夹则递归调用当前方法
 */
public class Demo063 {

    public static void main(String[] args) {
        // 创建文件对象:关联目标文件夹
        File dir = new File("/Users/pkxing/documents/119期就业班");
        printJavaFile(dir);
    }
    //  1. 定义方法:确定返回值和参数列表
    /**
     * 将指定文件夹下的所有java文件打印输出
     * @param dir 目标文件夹
     */
    public static void printJavaFile(File dir){
        // 1. 获得目标文件夹下的所有文件:得到文件数组
        File[] files = dir.listFiles();
        // 2. 遍历文件数组获得每个文件对象
        for (File file : files) {
            // 3. 判断是否是文件
            if (file.isFile()){
                // 判断是java文件
                if (file.getName().endsWith(".java")){
                    System.out.println(file);
                }
            } else {
                // 4. 如果是文件夹则递归调用当前方法
                printJavaFile(file);
            }
        }
    }
}

11.IO流简介

package com.itheima._07IO流简介;

/**
    目标:能够说出IO流的作用

    讲解:
        1. 为什么要学习IO流
             目前数据使用集合和数组,集合或数组保存在内存中的,内存是临时性存储,
             一旦电脑断电或程序重新启动,数据就没有了。
             如果需要保证数据永久存储,就希望将数据存储到硬盘的文件中。
             通过IO流我们就可以将数据保存到文件中,也可以从文件中读取数据到程序中。

        2. IO流的作用
            保存数据:将内存中的数据保存硬盘上的文件中
            读取数据:将文件中的数据读取到程序中

        3. 什么是IO
            Input:输入: 文件到内存中
            Output:输出:内存到文件中

    小结:
        IO流的作用是什么
            保存数据到文件中
            读取数据到内存中

 */
public class Demo07 {
}

12.IO流分类

package com.itheima._08IO流分类;

/**
    目标:能够说出IO流的分类

    讲解:
        1. IO流的分类
            按照流向分类
                输入流:将文件中数据读取到内存中
                输出流:将内存中数据保存文件中

            按照数据类型分类
                字节流:以字节为单位进行读写数据
                字符流:以字符为单位进行读写数据

            字节输入流(InputStream):以字节为单位进行读取数据
            字节输出流(OutputStream):以字节为单位进行输出数据

            字符输入流(Reader):以字符为单位进行读取数据
            字符输出流(Writer):以字符为单位进行输出数据

        2. 如何判断流是字符流还是字节流
            * 根据类的名称判断,如果是以Stream结尾,则就是字节流,否则都是字符流。

    小结:
        1. IO流按流向分为哪2类?
            输入流
            输出流

        2. IO流按数据类型分为哪2类?
            字节流
            字符流
 */
public class Demo08 {

}

13.数据本质

package com.itheima._09数据本质;

/**
    目标:能够说出数据的本质是什么

    讲解:
        1. 科普计算机小常识
            * 计算机只能识别0和1
            * 任何数据存储在内存中都是0和1(二进制数据)
            * 任何数据在传输过程中都是二进制数据

            01010110010  ==> 机器语言
            mov #        ==> 汇编语言
            java/c/c++   ==> 高级语言

        2. 编码和解码概述
            编码:将字符转换为二进制数据的过程
                比如:a ==> 码表 ==> 97 ==> 01010110
            解码:将二进制数据转换为字符的过程
                比如:01010110 ==> 97 ==> 码表 ==> a

    小结:
        1. 数据的本质是什么:二进制数据
 */
public class Demo09 {
}

14.字节输出流

package com.itheima._10字节输出流;

/**
     目标:掌握OutputStream类的作用和方法

     讲解:
         1. OutputStream类概述
            Output:输出
            Stream:流
            是字节输出流:以字节为单位输出数据
            是一个抽象类,不能直接创建对象,只能创建子类对象
            是所有字节输出流的父类

         2. OutputStream类常用方法
             void  close()   关闭流释放资源

             void  write(byte[] b)
                输出一个字节数组内容到文件中
             void  write(byte[] b, int off, int len)
                输出字节输出的一部分内容到文件中
             void  write(int b)
                输出一个字节到文件中

         3. OutputStream类常用子类
            FileOutputStream

     小结:
         1.OutputStream类的作用:以字节为单位输出数据到文件中

         2.OutputStream类用来输出数据的方法
            write
 */
public class Demo101 {
}

package com.itheima._10字节输出流;

import java.io.File;
import java.io.FileOutputStream;

/**
    目标:使用FileOutputStream类向文件输出字节

    讲解:
        1. FileOutputStream类概述
            继承OutputStream,字节输出流:以字节为单位输出数据到文件中

        2. FileOutputStream类常用构造方法
             FileOutputStream(String filename)
                * 根据文件路径字符串创建字节输出流对象
             FileOutputStream(File file)
                * 根据文件对象创建字节输出流对象
                * 如果目标文件不存在,则会自动创建

        3. FileOutputStream类使用步骤
            1. 创建字节输出流并关联目标文件
            2. 调用字节输出流对象的write方法输出数据
            3. 调用字节输出流对象的close方法关闭流释放资源

    小结:
        使用FileOutputStream类向文件输出字节的步骤
            1. 创建流关联目标文件
            2. 调用write方法输出数据
            3. 调用close方法关闭流释放资源
 */
public class Demo102 {
    public static void main(String[] args) throws Exception {
        // 1. 创建字节输出流并关联目标文件
        FileOutputStream fos = new FileOutputStream(new File("a.txt"));
        // 2. 调用字节输出流对象的write方法输出数据
        fos.write(97);  // a
        fos.write(98);  // b
        // 300 ==> 00000000 00000000 00000001 00101100
        // 44 ==> 00101100
        fos.write(300); // ,
        fos.write(44); // ,
        // 3. 调用字节输出流对象的close方法关闭流释放资源
        fos.close();
    }
}

package com.itheima._10字节输出流;

import java.io.FileOutputStream;
import java.io.OutputStream;

/**
    目标:使用FileOutputStream类向文件输出字节数组

    讲解:
        1. OutputStream类与写出字节数组相关的方法
            void write(byte[] buf) 输出整个字节数组的内容
            void write(byte[] buf,int off,int length) 输出字节数组的部分内容

    小结:
        使用FileOutputStream类向文件输出字节数组的步骤
            1. 创建流关联目标文件
            2. 调用write方法传递字节数组
            3. 调用close方法关闭流释放资源
 */
public class Demo103 {
    public static void main(String[] args) throws Exception{
        // 1. 创建流关联目标文件
        OutputStream fos = new FileOutputStream("b.txt");
        // 2. 调用write方法输出字节数组
        // 2.1 定义字节数组
        byte[] buf = {97,98,99,100,101};
        // 2.2 输出整个字节数组内容
        fos.write(buf); // abcde
        // 2.3 输出字节数组的部分内容
        fos.write(buf, 1, 3); // bcd

        // 2.3 定义字符串
        String str = "你好师姐";
        // 将字符串转换为字节数组
        byte[] bytes = str.getBytes();
        fos.write(bytes);

        // 3. 调用close方法关闭流释放资源
        fos.close();
    }
}

package com.itheima._10字节输出流;

import java.io.FileOutputStream;

/**
    目标: 使用FileOutputStream实现追加写出数据

    讲解:
        1. FileOutputStream类与追加写出数据相关的构造方法
             FileOutputStream(String file,boolean append)
             FileOutputStream(File file,boolean append)
                * append:true 追加输出,不会清空目标文件的内容
                * append:false 不追加输出,会清空目标文件的内容,再输出数据,默认值

        2. 如何实现换行输出
            输出一个换行符:
            \r  回车符
            \n  换行符
            \r\n  换行符(推荐使用)


    小结:
        1. 如何追加输出数据
            在创建流的构造方法中通过第二参数指定true即可

        2. 如何实现换行输出数据
            输出一个换行符:\r\n
 */
public class Demo104 {
    public static void main(String[] args)throws Exception {
        // 创建流关联目标文件
        FileOutputStream fos = new FileOutputStream("b.txt", true);

        // 输出数据
        fos.write("你好\r\n".getBytes());

        // 输出一个换行符
        // fos.write("\r\n".getBytes());

        // 关闭流释放资源
        fos.close();
    }
}

package com.itheima._10字节输出流;

import java.io.File;
import java.io.FileOutputStream;

/**
    目标:理解IO流使用的注意事项

    注意事项小结
        1. 创建流关联目标文件必须是普通文件不能关联文件夹
            * java.io.FileNotFoundException: /Users/pkxing/documents/aaa (Is a directory)
        2. 流一旦关闭就不能再使用了
 */
public class Demo105 {
    public static void main(String[] args) throws Exception {
        // 创建流关联文件
        FileOutputStream fos = new FileOutputStream("/Users/pkxing/documents/aaa.txt");
        // 输出数据
        fos.write("aaa".getBytes());
        // 关闭流
        fos.close();

        // 输出数据
        // Stream Closed:流已经关闭了
        fos.write("bbb".getBytes());
    }
}

15.字节输入流

package com.itheima._11字节输入流;

/**
     目标:掌握InputStream类的作用和方法

     讲解:
         1. InputStream类概述
            Input:输入
            Stream:字节流
            是一个字节输入流:以字节为单位从文件中读取数据到内存中
            是一个抽象流,不能创建对象,只能创建子类对象
            是所有字节输入流的父类

         2. InputStream类常用子类
            FileInputStream

         3. InputStream类常用方法
             void  close() 关闭流释放资源
             int   read()
                从流关联的目标文件中读取一个字节
                返回实际读取到的字节数
                如果读取到文件末尾,返回值为-1

             int   read(byte[] b)
                从流关联的目标文件中读取一个字节数组
                返回实际读取到字节个数
                如果读取到文件末尾,返回值为-1

             int   read(byte[] b, int off, int len)
                 从流关联的目标文件中读取一个字节数组
                 返回实际读取到字节个数
                 如果读取到文件末尾,返回值为-1

     小结:
         1.InputStream类的作用:以字节为单位读取数据

         2.InputStream类用来读取数据的方法
            read

 */
public class Demo111 {
}

package com.itheima._11字节输入流;

import java.io.FileInputStream;

/**
    目标:使用FileInputStream类从文件中读取一个字节数据

    讲解:
        1. FileInputStream类概述
            继承InputStream:以字节为单位读取数据

        2. FileInputStream类构造方法
            FileInputStream(String pathname)
            FileInputStream(File file)
                根据文件路径字符串或文件对象创建字节输入流对象
                如果目标文件不存在则直接抛出异常

        3. FileInputStream类读取数据使用步骤
            1. 创建字节输入流关联目标文件
            2. 调用字节输入流的read方法:从文件中读取数据
            3. 调用字节输入流的close方法:关闭流释放资源

    小结:
        使用字节输入流从文件中读取数据的步骤:
             1. 创建字节输入流关联目标文件
             2. 调用字节输入流的read方法:从文件中读取数据
             3. 调用字节输入流的close方法:关闭流释放资源
 */
public class Demo112 {
    public static void main(String[] args) throws Exception {
        // 1. 创建字节输入流关联目标文件
        FileInputStream fis = new FileInputStream("a.txt");

        // 2. 调用字节输入流的read方法:从文件中读取数据
       /* int len = fis.read(); // 97
        System.out.println("len = " + (char)len); // a

        len = fis.read();
        System.out.println("len = " + (char)len); // b

        len = fis.read();
        System.out.println("len = " + (char)len); // c

        len = fis.read();
        System.out.println("len = " + len); // -1*/


        // 使用循环改进
        // 定义整型变量:接收实际读取到的字节数
        int len = -1;
        // 使用循环读取数据
        // abc
        while((len = fis.read()) != -1){
            System.out.print((char) len);
        }
        // 3. 调用字节输入流的close方法:关闭流释放资源
        fis.close();
    }
}

package com.itheima._11字节输入流;

import java.io.FileInputStream;

/**
    目标:使用FileInputStream类从文件中读取字节数组

    讲解:
        1. InputStream类与读取字节数组相关的方法
            int read(byte[] buf)
                * 从流关联的目标文件中读取数据到字节数组中
                * 返回实际读取到的字节个数
                * 如果读取到文件末尾-1

        2. 字节输入流读取字节数组的步骤
            1. 创建流关联目标文件
            2. 创建字节数组:用来存储读取到的数据
            3. 调用字节输入流的read方法读取数据到字节数组中
            4. 关闭流释放资源

    小结:
        1. 使用FileInputStream从文件中读取字节数组的步骤
             1. 创建流关联目标文件
             2. 创建字节数组:用来存储读取到的数据
             3. 调用字节输入流的read方法读取数据到字节数组中
             4. 关闭流释放资源

 */
public class Demo113 {
    public static void main(String[] args) throws Exception{
        // 1. 创建流关联目标文件
        FileInputStream fis = new FileInputStream("a.txt");
        // 2. 创建字节数组:用来存储读取到的数据
        byte[] buf = new byte[1024];
        // 1025 1024
        // 定义变量接收实际读取到的字节个数
        int len = -1;
        while ((len = fis.read(buf)) != -1){
            System.out.print(new String(buf,0,len)); // 1024
        }
        // 4. 关闭流释放资源
        fis.close();
    }

    // 没有使用循环
    public static void test01() throws Exception{
        // 1. 创建流关联目标文件
        FileInputStream fis = new FileInputStream("a.txt");
        // 2. 创建字节数组:用来存储读取到的数据
        byte[] buf = new byte[2];
        // 3. 调用字节输入流的read方法读取数据到字节数组中
        int len = fis.read(buf);
        System.out.println("len = " + len); // 2
        System.out.println("buf = " + new String(buf)); // ab

        // 再读取一次
        len = fis.read(buf);
        System.out.println("len = " + len); // 2
        System.out.println("buf = " + new String(buf)); // cd

        // 再读取一次
        len = fis.read(buf);
        System.out.println("len = " + len); // 1
        System.out.println("buf = " + new String(buf)); // ed

        // 再读取一次
        len = fis.read(buf);
        System.out.println("len = " + len); // -1
        System.out.println("buf = " + new String(buf)); // ed

        // 4. 关闭流释放资源
        fis.close();
    }
}

package com.itheima._11字节输入流;

/**
    目标:能够理解读取数据read(byte[] b)方法的原理

    讲解:
        1. 画图分析read(byte[] b)方法读取数据的原理

    小结:
        read(byte[] b)方法的原理:
            每次从流关联的目标文件中读取数据到指定的字节数组中,
            每次都是将读取到数据从数组的索引0位置开始存储
 */
public class Demo114 {

}

16.字节流复制文件

package com.itheima._12字节流复制文件;

import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
    目标:能够使用字节流实现文件的复制:将"d:/aaa/a.png" 复制到 "e:/bbb/a.png"

    讲解:
        1. 画图分析文件复制流程

        2. 文件复制实现步骤
            1. 创建字节输入流关联源文件:必须要存在
            2. 创建字节输出流关联目标文件:可以没有
            3. 使用字节输入流循环读取源文件数据
            4. 使用字节输出流将数据输出到目标文件中
            5. 关闭流释放资源
    小结:
        1. 字节流复制文件的步骤
             1. 创建字节输入流关联源文件:必须要存在
             2. 创建字节输出流关联目标文件:可以没有
             3. 使用字节输入流循环读取源文件数据
             4. 使用字节输出流将数据输出到目标文件中
             5. 关闭流释放资源
 */
public class Demo12 {
    public static void main(String[] args) throws Exception {
        // 1. 创建字节输入流关联源文件:必须要存在
        FileInputStream fis = new FileInputStream("/Users/pkxing/documents/aaa.mp4");
        // 2. 创建字节输出流关联目标文件:可以没有
        FileOutputStream fos = new FileOutputStream("/Users/pkxing/documents/bbb.mp4");
        // 3. 使用字节输入流循环读取源文件数据
        // 创建字节数组:用来存储读取的数据
        byte[] buf = new byte[1024];
        // 定义整型变量:接收实际读取到的字节个数
        int len = -1;
        while ((len = fis.read(buf)) != -1){
            // 4. 使用字节输出流将数据输出到目标文件中
            fos.write(buf,0,len);
        }
        // 5. 关闭流释放资源
        fis.close();
        fos.close();
    }
}

17.字节流操作字符问题

package com.itheima._13字节流操作字符问题;

import java.io.FileInputStream;

/**
    目标:了解字节流不方便读取字符数据

    小结:
        字节流读取字符很不方便。容易出现乱码问题
 */
public class Demo13 {
    public static void main(String[] args)throws Exception{
        // 创建字节输入流
        FileInputStream fis = new FileInputStream("a.txt");
        int len = -1;
        // 读取数据
        while((len = fis.read()) != -1){
            // a你好
            // 你 : -100 -123 111
            // 汉字:GBK码表: 一个汉字占两个字节
            // 汉字:UTF8码表: 一个汉字占三个字节
            System.out.print((char)len); // a
        }
        // 关闭流释放资源
        fis.close();
    }
}

以下解决

18.字符输入流

package com.itheima._14字符输入流;

/**
    目标:掌握Reader类的作用和方法

    讲解:
         1. Reader类概述
            是所有字符输入流父类,是一个抽象类
            以字符为单位读取数据

         2. Reader类常用子类
            FileReader

         3. Reader类常用方法
             void   close() 关闭流释放资源
             int   read()
                从流关联的目标文件中读取一个字符
                返回实际读取到的字符数
                如果读取到文件末尾,返回值-1

             int   read(char[] cbuf)
                从流关联的目标文件中读取数据到指定的字符数组
                返回实际读取到字符个数
                如果读取到文件末尾,返回值-1
             int   read(char[] cbuf, int off, int len)
                 从流关联的目标文件中读取数据到指定的字符数组
                 返回实际读取到字符个数
                 如果读取到文件末尾,返回值-1

    小结:
        Reader类作用:以字符为单位读取数据

        读取数据的方法:read
 */
public class Demo141 {
}

package com.itheima._14字符输入流;

import java.io.FileReader;

/**
    目标:使用字符输入流FileReader读取文本数据

    讲解:
        1. FileReader类概述
            继承Reader:字符输入流,以字符为单位读取数据

        2. FileReader类常用构造方法
            FileReader(String path)
            FileReader(File file)
                 根据文件路径字符串或文件对象创建字符输入流
                 如果目标文件不存在,则抛出异常

        3. 字符输入流的使用步骤
            1. 创建流关联目标文件
            2. 调用read方法读取数据
            3. 调用close方法关闭流释放资源

    小结:
        FileReader读取数据的步骤
             1. 创建流关联目标文件
             2. 调用read方法读取数据
             3. 调用close方法关闭流释放资源

 */
public class Demo142 {

    public static void main(String[] args) throws Exception{
        // 一次读取一个字符
        // readChar();

        // 一次读取一个字符数组
        readCharArray();
    }

    /*
     一次读取一个字符数组
     */
    private static void readCharArray()throws Exception {
        // 1. 创建流关联目标文件
        FileReader fr = new FileReader("a.txt");

        // 2. 读取一个字符数组
        /*// a你好
        char[] buf = new char[2];
        int len = fr.read(buf); // 好你
        System.out.println("len = " + len); // 2
        System.out.println("buf = " + new String(buf)); //  a你


        len = fr.read(buf); // 好
        System.out.println("len = " + len); // 1
        System.out.println("buf = " + new String(buf)); //  好你

        len = fr.read(buf);
        System.out.println("len = " + len); // -1
        System.out.println("buf = " + new String(buf)); //  好你*/

        // 2. 创建字符数组:用来存储读取到的数据
        char[] buf = new char[1024];
        // 定义变量接收实际读取到的字符个数
        int len = -1;
        while ((len = fr.read(buf)) != -1){
            System.out.print(new String(buf,0,len));
        }
        // 3. 调用close方法关闭流释放资源
        fr.close();
    }

    /*
        一次读取一个字符
     */
    private static void readChar() throws Exception{
        // 1. 创建流关联目标文件
        FileReader fr = new FileReader("a.txt");
        // 2. 调用read方法读取数据
        // a你
        /*System.out.println((char) fr.read()); // a
        System.out.println((char) fr.read()); // 你
        System.out.println(fr.read()); // -1*/

        // 定义变量:接收读取到的字符数
        int len = -1;
        // 使用循环读取
        while((len = fr.read()) != -1){
            System.out.print((char) len);
        }

        // 3. 调用close方法关闭流释放资源
        fr.close();
    }
}

19.字符输出流

package com.itheima._15字符输出流;

/**
     目标:掌握Writer类的作用和方法

     讲解:
         1. Writer类概述
            是一个抽象类,不能直接创建对象,只能创建子类对象
            是所有字符输出流的父类:以字符为单位输出数据

         2. Writer类常用子类
            FileWriter

         3. Writer类常用方法
             void close();
             void  write(char[] cbuf)
                输出一个字符数组
             void  write(char[] cbuf, int off, int len)
                输出字符数组的一部分
             void  write(int c)
                输出一个字符

             void  write(String str)
                输出一个字符串
             void  write(String str, int off, int len)
                输出字符串的一部分

     小结:
        Writer类的作用:以字符为单位输出数据到文件中
        输出数据的方法:write
 */
public class Demo151 {

}

package com.itheima._15字符输出流;

import java.io.FileWriter;

/**
 目标:能够使用字符输出流FileWriter往文件中输出字符数据

 讲解:
     1. FileWriter类概述
        继承Writer,字符输出流:以字符为单位输出数据

     2. FileWriter类常用构造方法
        FileWriter(String path)
        FileWriter(String path,boolean append)
        FileWriter(File file)
        FileWriter(File file,boolean append)
            根据文件路径字符串或文件对象创建字符输出流
            append:true 追加输出,false,不追加

     3. 字符输出流使用步骤
        1. 创建流关联目标文件
        2. 调用write方法输出数据
        3. 调用close方法关闭流释放资源

 小结:
        FileWriter 输出数据的步骤
         1. 创建流关联目标文件
         2. 调用write方法输出数据
         3. 调用close方法关闭流释放资源
 */
public class Demo152 {
    public static void main(String[] args) throws Exception{
        // 输出字符数组
        // writeCharArray();

        // 输出字符串
        writeString();
        
    }

    // 输出字符串
    private static void writeString() throws Exception {
        // 1. 创建流关联目标文件
        FileWriter fw = new FileWriter("d.txt",true);
        String str = "你好世界te(str);";
        // 2. 调用write方法输出数据
        // 输出整个字符串
        fw.write(str);
        // 输出字符串部分内容
        fw.write(str, 1, 2);
        fw.write("\r\n");
        // 3. 调用close方法关闭流释放资源
        fw.close();
    }

    /**
     * 输出字符数组
     */
    private static void writeCharArray() throws Exception{
        // 1. 创建流关联目标文件
        FileWriter fw = new FileWriter("d.txt");
        char[] buf = {'你','好','师','妹'};
        // 2. 调用write方法输出数据
        // 输出整个字符数组
        fw.write(buf);
        // 输出字符数组部分内容
        fw.write(buf, 1, 2);
        // 3. 调用close方法关闭流释放资源
        fw.close();
    }
}

20.close和flush方法区别

package com.itheima._16close和flush方法区别;

import java.io.FileWriter;

/**
    目标:能够阐述flush方法和close方法的区别(面试题)

    讲解:
        1. flush方法和close方法的区别
            flush方法:用来刷新缓冲区,流还可以继续使用
            close方法:关闭流释放资源,流一旦就不能使用,内部会调动flush方法。

        2. 演示flush方法和close方法

    小结:
        1. flush和close方法的区别
             flush方法:用来刷新缓冲区,流还可以继续使用
             close方法:关闭流释放资源,流一旦就不能使用,内部会调动flush方法。
 */
public class Demo161 {
    public static void main(String[] args) throws Exception{
        // 创建字符输出流
        FileWriter fw = new FileWriter("e.txt");
        // 输出数据
        fw.write("你好");

        // 刷新缓冲区:将数组的内容输出目标文件中
        fw.flush();

        fw.write("世界");

        // 关闭流释放资源
        fw.close();
    }
}

21.总结

package com.itheima._17教学目标小结;

import java.util.concurrent.locks.ReentrantLock;

/**
 教学目标
 - 能够说出File对象的创建方式
         File(String path)
         File(String parent,String child)
         File(File parent,String child)

 - 能够使用File类常用方法
    getName
    getAbsolutePath
    getPath
    length
    getParentFile

    exists
    isDirectory
    isFile

    createNewFile
    mkdirs
    mkdir

    delete
    listFiles

 - 能够辨别相对路径和绝对路径
    绝对路径:以盘符开始
    相对路径:没有以盘符开始,相当于当前项目根目录

 - 能够遍历文件夹
    1. File dir = new File("目标文件夹");
    2. File[] files = dir.listFiles();
    3. for(File f:files) { }

 - 能够解释递归的含义:方法A调用方法A

 - 能够使用递归的方式计算5的阶乘:参考代码
 - 能够说出使用递归会内存溢出隐患的原因
    因为方法一直进栈导致栈内存不够

 - 能够说出IO流的分类和功能
     字节输入流
     字节输出流
     字符输入流
     字符输出流

        保存数据和读取数据

 - 能够使用字节输出流写出数据到文件
        1. 创建流关联目标文件
        2. 调用write方法输出数据
        3. 调用close方法关闭流

 - 能够使用字节输入流读取数据到程序
         1. 创建流关联目标文件
         2. 调用read方法读取数据
         3. 调用close方法关闭流

 - 能够理解读取数据read(byte[])方法的原理
     将读取到文件数据存储到字节输出中
     每次从索引0位置开始存储读取到数据

 - 能够使用字节流完成文件的复制
    参考代码

 - 能够使用FileWriter写数据到文件
     1. 创建流关联目标文件
     2. 调用write方法输出数据
     3. 调用close方法关闭流

 - 能够说出FileWriter中关闭和刷新方法的区别
     flush方法:用来刷新缓冲区,流还可以继续使用
     close方法:关闭流释放资源,流一旦就不能使用,内部会调动flush方法

 - 能够使用FileWriter写数据的5个方法
    write(int ch)
    write(char[] buf)
    write(char[] buf,int off,int len)
    write(String str)
    write(String str,int off,int len)

 - 能够使用FileWriter写数据实现换行和追加写
    追加:指定构造方法第二个参数为true
    换行:输出一个\r\n

 - 能够使用FileReader读数据
     1. 创建流关联目标文件
     2. 调用read方法读取数据
     3. 调用close方法关闭流

 - 能够使用FileReader读数据一次一个字符数组

 学生反馈
 - Java中线程池运行原理, 通过集合、映射或数组方式获取流, 这俩方面有点迷

 知识回顾
    1. 如何实现线程安全
        同步代码块:synchronized(锁对象){ 操作共享资源的代码 }
        同步方法:修饰符 synchronized 返回值类型 方法名(){ 操作共享资源的代码 }
        Lock接口:常用子类:ReentrantLock
            void lock() 获取锁
            void unlock() 释放锁

    2. 如何提交任务到线程池
         * 创建线程池对象并指定线程数量
            * ExecutorService tp = Executors.newFixedThreadPool(3);
         * 提交Runnable任务:创建Runnable接口实现类对象重写run方法:封装任务代码
         * 提交Callable任务:创建Callable接口实现类对象重写call方法:封装任务代码
            * tp.submit(Runnable r 或 Callable c);
         * 销毁线程池:tp.shutdown();

    3. Lambda表达式格式和使用条件
        * 作用:简化匿名内部类的语法
        * 使用前提条件:接口类型且有且只有一个抽象方法
        * 标准格式:(参数列表)->{ 方法体 }
                * 参数列表:就是接口抽象方法的参数列表
                * 方法体:就是接口抽象方法的方法体:对抽象方法的实现
        * 省略格式:变量名 -> 一条语句
            * 只有一个参数:可以省略小括号
            * 只有一条语句:可以大括号

    4. Stream流常用方法
        * 作用:对集合或数组中元素进行加工处理。
        * 如何获得Stream流对象
            * Stream  stream = 单列集合对象.stream();
            * Stream  stream = Stream.of(数组)
        * 常用方法:
            * forEach:遍历流中元素并传递消费者
                * 参数:Consumer接口实现类对象,Consumer是一个函数式接口,抽象方法:void accept(T t);
            * filter:对流元素进行过滤,通过Predicate接口封装过滤条件
                * Predicate是一个函数式接口,抽象方法:boolean test(T t)
            * limit: 获取前n个
            * skip:跳过前n个
            * map: 将流的元素从一种数据类型转换为另一中数据类型
                * Function是一个函数式接口,抽象方法:R apply(T t)
            * count:获得流元素个数
            * concat:流合并
            * collect:收集流中元素(数组或集合中)
                * stream.collect(Collectors.toList())
                * stream.collect(Collectors.toSet())
                * stream.toArray()
                * stream.toArray(String[]::new)

    今天内容
        1. File类
            常用方法
        2. 递归
            概念和注意事项
        3. IO流(4个类)
            * 实现数据的保存和读取操作
            * 知道如何选择
    重点:
        1. File常用方法
        2. 能够使用IO读写数据:一次读取一个数组,一个输出一个数组
 */
public class Demo17 {
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值