笔记17-File&递归&字节流

File类

File类概述和构造方法

File: 它是文件和目录路径名的抽象表示

  • 文件和目录是可以通过File封装成的对象的
  • 对于File而言,其封装的并不是一个真正存在的文件, 仅仅是一个路径名而已. 它可以是存在的,也可以是不存在的,将来是要通过具体的操作把这个路径的内容转换为具体存在的

在这里插入图片描述

package com.itdemo_25;

import java.io.File;

public class FileDemo01 {
    public static void main(String[] args) {
//        File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
        File f1 = new File("E:\\itcast\\java.txt");//抽象路径的表示形式,不一定需要路径存在
        System.out.println(f1);

//        File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例
        File f2 = new File("E:\\itcast","java.txt");
        System.out.println(f2);

//        File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例
        File f3= new File("E:\\itcast");
        File f4 = new File(f3,"java.txt" );
        System.out.println(f4);
    }
}

File类创建功能

在这里插入图片描述

package com.itdemo_25;

import java.io.File;
import java.io.IOException;
/*
        public boolean createNewFile()当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空 文件
            如果文件不存在,就创建文件,并返回true
            如果文件存在,就不创建文件,返回false
        public boolean mkdir() 创建由此抽象路径名命名的目录
            如果目录不存在,就创建目录,并返回true
            如果目录存在,就不创建目录.并返回false
        public boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
            如果目录不存在,就创建目录,并返回true
            如果目录存在,就不创建目录.并返回false
*/
public class FileDemo02 {
    public static void main(String[] args) throws IOException {

        //需求1:我要在D:\\itcast目录下创建一个文件java.txt
        File f1 = new File("D:\\itcast\\java.txt");
        System.out.println(f1.createNewFile());

        //需求2:我要在D:\\itcast目录下创建一个目录JavaSE
        File f2 = new File("D:\\itcast\\JavaSE");
        System.out.println(f2.mkdir());

        //需求3:我要在D:\\itcast目录下创建一个多级目录JavaWEB\\HTML
        File f3 = new File("D:\\itcast\\JavaWEB\\HTML");
//        System.out.println(f3.mkdir());//false
        System.out.println(f3.mkdirs());//true
        //需求4:我要在D:\\itcast目录下创建一个文件javase.txt
        File f4 = new File("D:\\itcast\\javase.txt");
//        System.out.println(f4.mkdir());
        //不能根据路径名来判断是目录还是文件,要根据使用的方法来判断
        System.out.println(f4.createNewFile());//不能出现命名一样的,不论是目录还是文件
    }
}

File类的判断和获取功能

在这里插入图片描述

package com.itdemo_25;


import java.io.File;

/*
判断功能
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在

获取功能
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回由此抽象路径名表示的文件或目录的名称
public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组


 */
public class FileDemo03 {
    public static void main(String[] args) {
        //创建一个File对象
        File f = new File("D:\\IDEADemo\\Demo\\src\\java.txt");
//        public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
        System.out.println(f.isDirectory());

//        public boolean isFile() 测试此抽象路径名表示的File是否为文件
        System.out.println(f.isFile());

//        public boolean exists() 测试此抽象路径名表示的File是否存在
        System.out.println(f.exists());

//        public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
//        public String getPath() 将此抽象路径名转换为路径名字符串
//        public String getName() 返回由此抽象路径名表示的文件或目录的名称
        System.out.println(f.getAbsolutePath());
        System.out.println(f.getPath());
        System.out.println(f.getName());
//        public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
        File f2 = new File("D:\\itcast");
        String[] strArray = f2.list();
        for(String str : strArray){
            System.out.println(str);
        }
        System.out.println("-----");
        //public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组
        File[] fileArray = f2.listFiles();
        for(File file : fileArray){
//            System.out.println(file);//获取绝对路径
//            System.out.println(file.getName());//获取名称
            //只获取文件的名称
            if (file.isFile()){
                System.out.println(file.getName());
            }
        }
    }
}

File类的删除功能

在这里插入图片描述
绝对路径和相对路径的区别

  • 绝对路径: 完整的路径名,不需要任何其他信息就可以定位它所表示的文件.例如: D:\itcast\java.txt
  • 相对路径: 必须使用取自其他路径名的信息进行解释. 例如myFile\java.txt

删除目录时的注意事项

  • 如果一个目录中有内容(目录,文件),不能直接删除,应该先删除目录中的内容,最后才能删除目录.
package com.itdemo_25;

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

public class FileDemo04 {
    public static void main(String[] args) throws IOException {
//        File f1 = new File("D:\\itcast\\java.txt");
        //需求1: 在当前模块目录下创建java.txt文件
        File f1 = new File("java.txt" );
        System.out.println(f1.createNewFile());
//        需求2: 删除当前模块目录下的java.txt
//        System.out.println(f1.delete());
        System.out.println("--------");

//        需求3 :在当前文件目录下创建itcast目录
        File f2 = new File("src\\com\\itdemo_25\\itcast");
//        System.out.println(f2.mkdir());

        //需求4: 删除当前模块目录下的itcast
        System.out.println(f2.delete());
        System.out.println("---------");

        //需求5: 在当前模块下创建一个目录itcast,然后在目录下创建一个文件java.txt
        File f3 = new File("src\\itcast");
        System.out.println(f3.mkdir());
        File f4 = new File("src\\itcast\\java.txt");
        System.out.println(f4.createNewFile());

//        需求6: 删除当前模块下的目录itcast
        System.out.println(f4.delete());
        System.out.println(f3.delete());
    }
}

递归

递归概述: 以编程的角度来看,递归指的是方法定义中调用方法本身的现象

递归解决问题的思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算

递归解决问题要找到两个内容:

  • 递归出口: 否则会出现内存溢出
  • 递归规则: 与原问题相似的规模较小的问题
package com.itdemo_25;

public class DiGuDemo {
    public static void main(String[] args) {
        //回顾不死神兔:  求第20个月兔子的对数
        //每个月兔子对数: 1,1,2,3,5,8.....
        int[] arr= new int[20];

        arr[0] =1;
        arr[1] =1;

        for(int i=2; i<arr.length;i++){
            arr[i] =arr[i-1]+arr[i-2];
        }
        System.out.println(arr[19]);
        System.out.println(f(20));
    }

    /*
    递归解决问题: 首先就是定义一个方法,
         定义一个方法f(n):表示第n个月的兔子对数
         那么,第n-1个月的兔子对数该如何表示呢?f(n-1)
      同理,第n-2个月的兔子对数该如何表示呢?f(n-2)

   StackOverflowError:当堆栈溢出发生时抛出一个应用程序递归太深
     */
    public static int f(int n) {
        if (n == 1 || n == 2) {
            return 1;
        } else {
            return f(n - 1) + f(n - 2);
        }
    }
}

案例:递归求阶乘

需求:用递归求5的阶乘,并把结果在控制台输出

分析:
1.阶乘: 一个正整数的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n!
5! = 54321
2.递归出口: 1! = 1
3.递归规则:n!= n*(n-1)!
5! = 5*4!

思路:
1.定义一个方法,用于递归求阶乘,参数为一个int类型的变量
2.在方法内部判断该变量的值是否是1
是返回1
不是: 返回n*(n-1)!
3.调用方法
4.输出结果

package com.itdemo_25;

public class DiGuDemo01 {
    public static void main(String[] args) {
        //调用方法
        int result = jc(5);
        System.out.println(result);
    }
    //定义一个方法,用于递归求阶乘,参数为一个int类型的变量
    public static int jc(int n){
        //在方法内部判断该变量的值是否是1
        if(n==1){
//            是返回1
            return 1;
        }else{
            //不是返回n*(n-1)!
            return n*jc(n-1);
        }
    }
}

案例: 遍历目录

需求:给定一个路径(D:\itcast),通过递归完成遍历该目录下所有内容,并把所有文件的绝对路径输出在控制台
思路:

  1. 根据给定的路径创建一个File对象
  2. 定义一个方法, 用于获取给定目录下的所有内容,参数为第一步创建的File对象
  3. 获取给定的File目录下所有的文件或者目录的File数组
  4. 遍历该File数组,得到每一个File对象
  5. 判断该File对象是否是目录
    是:递归调用
    不是: 获取绝对路径输出在控制台
  6. 调用方法
package com.itdemo_25;

import java.io.File;

public class DiGuDemo02 {
    public static void main(String[] args) {
        //根据给定的路径创建一个File对象
        File srcFile = new File("D:\\itcast");
        //调用方法
        getAllFilePath(srcFile);
    }
    //定义一个方法,用于获取给定目录下的所有内容,参数为第一步创建爱你的File对象
    public static void getAllFilePath(File srcFile){
        //获取给定的File目录下所有文件或者目录的File数组
        File[] fileArray = srcFile.listFiles();
        //遍历该file数组,得到一个file对象
        if(fileArray != null){
            for(File file:fileArray){
                //判断该file对象是否是目录
                if(file.isDirectory()){
                    //是,递归调用
                    getAllFilePath(file);
                }else{
                    //不是,获取绝对路径
                    System.out.println(file.getAbsoluteFile());
                }
            }
        }
    }
}

IO流概述和分类

IO流概述:

  • IO: 输入/输出(Input/Output)
  • 流: 是一种抽象概念,是对数据传输的总称,也就是说数据在设备间的传输称为流,流的本质是数据传输
  • IO流就是用来处理设备间数据传输问题的
    常见的应用: 文件复制, 文件上传,文件下载

IO流的分类

  • 按照数据的流向
    • 输入流: 读数据
    • 输出流; 写数据
  • 按照数据类型来分
    • 字节流:
      • 字节输入流
      • 字节输出流
    • 字符流
      • 字符输入流
      • 字符输出流

IO流的使用场景

  • 如果操作是纯文本文件, 优先使用字符流
  • 如果操作的是图片/ 视频/音频/等二进制文件,优先使用字节流
  • 如果不确定文件类型,优先使用字节流,字节流是万能的流

字节流写数据

  • 字节流抽象基类
    • InputStream: 这个抽象类是表示字节输入流的所有类的超类
    • OutputStream: 这个抽象类是表示字节输出流的说有类的超类
    • 子类名特点:子类名称都是以其父类名作为子类名的后缀
  • 字节输出流:
    • FileOutputStream(String name): 创建文件输出流以指导的名称写入文件
  • 使用字节输出流写数据的步骤
    • 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
    • 调用字节输出流对象的写数据方法
    • 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
package com.itdemo_25;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo01 {
    public static void main(String[] args) throws IOException{
        //创建字节流输出对象
        //FileOutputStream(String name):创建文件输出流以指定的名称写入文件
        FileOutputStream fos = new FileOutputStream("src\\fos.txt");
        /*            
        做了三件事情:              
        A:调用系统功能创建了文件                
        B:创建了字节输出流对象                
        C:让字节输出流对象指向创建好的文件        
        */
        //void write(int b):将指定的字节写入此文件输出流
        fos.write(97);//a
        fos.write(57);//9
        fos.write(55);//7

        //最后都要释放资源        
        // void close():关闭此文件输出流并释放与此流相关联的任何系统资源。
        fos.close();
    }
}

字节流写数据的3种方式

在这里插入图片描述

package com.itdemo_25;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
构造方法
    FileOutputStream(String name) 创建文件输出流以指定的名称写入文件
    FileOutputStream(File file) 创建文件输出流以写入由指定的file对象表示问津
 */
public class FileOutputStreamDemo03 {
    public static void main(String[] args) throws IOException {

        //创建文件输出流以指定的名称写入文件
        FileOutputStream fos = new FileOutputStream("fos.txt");
//        new File(name);
//        FileOutputStream fos = new FileOutputStream(new File("fos.txt"));//与第一种方法相同

        //  FileOutputStream(File file) 创建文件输出流以写入由指定的file对象表示问津
        File file = new File("src\\fos.txt");
        FileOutputStream fos1 = new FileOutputStream(file);
        //可以等于
        FileOutputStream fos2 = new FileOutputStream(new File("src\\fos.txt"));

//      void write(int b) 将指定的字节写入此文件输出流 一次写一个字节数据
//        fos1.write(97);
//        fos1.write(98);
//        fos1.write(99);
//        void write(byte[] b)
//将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组 数据
        byte[] bys = {97,98,99,100};
//        fos1.write(bys);

//        void write(byte[] b, int off, int len)
// 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一 次写一个字节数组的部分数据
        fos1.write(bys,1,3);
        //释放资源
        fos1.close();
    }
}

字节流写数据的两个小问题

  • 字节流写数据如何实现换行
    • windows : \r\n
    • linux : \n
    • mac: \r
  • 字节流写数据如何实现追加写入
    • public FileOutputStream(String name; boolean append)
    • 创建文件输出流以指定的名称写入文件, 如果第二个参数为true, 则字节将写入文件的末尾而不是开头
package com.itdemo_25;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo04 {
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
        //只能在第一次创建时写入
//        FileOutputStream fos = new FileOutputStream("fox,txt");
//        再次运行重新写入,追加数据
        FileOutputStream fos = new FileOutputStream("fos1.txt",true);
        //写数据
        for(int i= 0; i<10;i++){
            fos.write("hello".getBytes());
            fos.write("\r\n".getBytes());
        }
        //释放资源
        fos.close();
    }
}


字节流写数据加异常处理

finally: 在异常处理时提供finally块来执行所有消除操作,比如说IO流中的释放资源
特点: 被finally控制语句一定会执行,除非JVM退出
异常处理格式:
try -catch-finally

try{
	可能出现异常的代码;
}catch(异常类名   变量名){
	异常的处理代码;
}fianlly{
	执行所有清除操作
}
package com.itdemo_25;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo05 {
    public static void main(String[] args) {
//        try {
//            FileOutputStream fos = new FileOutputStream("src\\fos1.txt");
//            fos.write("hello".getBytes());
//            fos.close();//释放资源就会被跳过,调用的资源就一直被占用
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        //加入finally来实现释放资源
        FileOutputStream fos =null;
        //创建目录不存在这出现FileNotFoundException异常
        try {
            fos = new FileOutputStream("src\\fos2.txt");
            fos.write("java".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //若创建的目录为空,,则保错所以
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字节流读数据(一次读一个字节数据)

  • 字节输入流
    • FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
  • 字节输入流读取数据的步骤
    • 创建字节输入流对象
    • 调用字节输入流对象的读取数据方法
    • 释放资源
package com.itdemo_25;

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo01{
    public static void main(String[] args) throws IOException {
        //创建字节输入流对象
        FileInputStream fis = new FileInputStream("src\\fos.txt");
        
        int by;
        /*          
        fis.read():读数据            
        by=fis.read():把读取到的数据赋值给by            
        by != -1:判断读取到的数据是否是-1        
        */

        while ((by=fis.read()) != -1){
            System.out.println((char)by);
        }

        fis.close();
    }
}

字节流读数据(一次读一个字节数组数据)

  • 一次读一个字节数组的方法
    • public int read(byte[] b):从输入流读取量最多b.length个字节的数据
    • 返回的是读入缓冲区的总字节数, 也就是实际的读取字节个数
package com.itdemo_25;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //创建字节输入对象
        FileInputStream fis = new FileInputStream("src\\fos.txt");
/*
        //调用字节输入流对象的读取方法
        byte[] bys = new byte[1024];
        //第一次读取
        int len = fis.read(bys);
        //读取的是实际读取的长度
        System.out.println(len);//5
//        String (byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
//        System.out.println(new String(bys));//javas
        System.out.println(new String(bys,0,len));

        //第二次读取
        len = fis.read(bys);
        System.out.println(len);//5
//        String (byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
//        System.out.println(new String(bys));//\r\nhel
        System.out.println(new String(bys,0,len));

        //第二次读取
        len = fis.read(bys);
        System.out.println(len);//5
//        String (byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
//        System.out.println(new String(bys));//lo\r\nw\r\n
        //String​(byte[] bytes, int offset, int length)
        System.out.println(new String(bys,0,len));//当实际长度到达-1时已经到达末尾了
        //与上一个的到结果相同,但上一种方法存在局限性,若byte数组长度为1000,将会在第一次读取的时候全部读取完
        */

//改进
        byte[] bys = new  byte[1024];//一般给予1024及其整数倍
        int len;
        while ((len =fis.read(bys))!=-1){
            System.out.println(new String(bys,0,len));
        }
        fis.close();
    }
}

案例: 复制文本文件

需求: 把“E:\itcast\窗里窗外.txt”复制到模块目录下的“窗里窗外.txt”
实现步骤

  • 复制文本文件,其实就把文本文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目 的地)
  • 数据源: E:\itcast\窗里窗外.txt — 读数据 — InputStream — FileInputStream
  • 目的地: myByteStream\窗里窗外.txt — 写数据 — OutputStream — FileOutputStream

思路:

  1. 根据数据源创建字节输入流对象
  2. 根据目的地创建字节输出流对象
  3. 读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
  4. 释放资源
package com.itdemo_25;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyTxtDemo {
    public static void main(String[] args) throws IOException {
        //1. 根据数据源创建字节输入流对象
        FileInputStream fis = new FileInputStream("D:\\BaiduNetdiskDownload\\窗里窗外.txt");
        //2. 根据目的地创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("src\\窗里窗外.txt");
        //3. 读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
        int by;
        while ((by=fis.read())!=-1){
            fos.write(by);
        }
        //4. 释放资源
        fis.close();
        fos.close();
    }
}

案例: 复制图片

案例需求
把“E:\itcast\mn.jpg”复制到模块目录下的“mn.jpg”
实现步骤

  1. 根据数据源创建字节输入流对象
  2. 根据目的地创建字节输出流对象
  3. 读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
  4. 释放资源
package com.itdemo_25;

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

public class CopyJpgDemo {
    public static void main(String[] args) throws IOException {
        //1.根据数据源创建字节输入流对象
        FileInputStream fis = new FileInputStream("D:\\BaiduNetdiskDownload\\mn.jpg");
        //2. 根据目的地创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("src\\mn.jpg");
        //3. 读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
        byte[] bys = new byte[1024];
        int len;
        while ((len=fis.read(bys) )!=- 1){
            fos.write(bys,0,len);
        }
        //4. 释放资源
        fis.close();
        fos.close();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值