第二十二天文件和Io流上

File:是java对于文件和文件夹抽象表现形式

构造方法:

public File(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。 如果给定的字符串是空字符串,则结果是空的抽象路径名。

public File(String parent,String child)

从父路径名字符串和子路径名字符串创建新的File实例。

public File(File parent,String child)

从父抽象路径名和子路径名字符串创建新的File实例。

File的功能:

创建功能:

public boolean createNewFile() 创建一个文件

public boolean mkdir() 创建一个文件夹

public boolean mkdirs() 创建多级文件夹

注意:
        1、要搞清楚你要创建文件还是文件夹
        2、骑白马的不一定王子,还有可能是唐僧,因为后缀名也是文件名字一部分,也可能是一个文件夹
删除功能:
    public boolean delete()
    注意:
        要想删除一个文件夹,这个文件里面必须是空的
重命名功能
    public boolean renameTo(File dest)
判断功能
    public boolean isDirectory()
    public boolean isFile()
    public boolean exists()
    public boolean canRead()
    public boolean canWrite()
    public boolean isHidden()
基本获取功能
    public String getAbsolutePath()
    public String getPath()
    public String getName()
    public long length()
    public long lastModified()
高级获取功能
    public String[] list()
    public File[] listFiles()
文件名称过滤器的实现思想及代码
    public String[] list(FilenameFilter filter)
    public File[] listFiles(FilenameFilter filter)

递归:方法定义中调用方法本身的现象

注意:

1、搞清楚递归和嵌套的区别:递归是方法定义的时候出现,嵌套是方法使用的时候出现的

2、递归要有出口条件(结束条件),如果没有,就成了死递归

IO流:(这里的输入输出,以java程序为参照物)

按照流向分类:

输入流

输出流

按照数据类型分类:

字节流

字节输入流 读取数据 InputStream

字节输出流 写出数据 OutputStream FileOutputStream

字符流

字符输入流 读取数据 Reader

字符输出流 写出数据 Writer

什么情况下,用字节流还是字符流,如果你操作的是记事本打开能看懂的数据,就用字符流,如果看不懂就用字节流

如果你不知道用什么流,就用字节流,字符流是建立在字节流的基础上出现的。

我们想要实现IO操作,就必须要知道硬盘上文件的表现形式

Java提供了一个类让我们操作硬盘上的文件:File

File也就是文件表现形式 File:文件和目录(文件夹)路径名的抽象表示。

构造方法:

public File(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。 如果给定的字符串是空字符串,则结果是空的抽象路径名。

public File(String parent,String child)

从父路径名字符串和子路径名字符串创建新的File实例。

public File(File parent,String child)

从父抽象路径名和子路径名字符串创建新的File实例。

import java.io.File;

public class FileDemo1 {
    public static void main(String[] args) {
        //public File(String pathname) 根据一个路径得到一个File对象
        //F:\a.txt封装成一个File对象
        File file = new File("F:\\a.txt");
        System.out.println(file);

        //public File(String parent,String child)
        //父的路径:F:\demo
        //子路径:b.txt
        File file1 = new File("F:\\demo", "b.txt");
        System.out.println(file1);
        //public File(File parent,String child)
        //父的路径:F:\demo
        //子路径:b.txt
        File file2 = new File("F:\\demo");
        File file3 = new File(file2, "b.txt");
        System.out.println(file3);
    }
}

创建功能

public boolean createNewFile()

public boolean mkdir()

public boolean mkdirs()

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

public class FileDemo2 {
    public static void main(String[] args) {
        //需求:我想在E盘下面创建一个文件夹demo2
        //封装成File对象,不需要文件或者目录是否已经存在,它只是将一个路径抽象的用File表示
        //将来你可以用File类中的一些方法,来进行创建或者删除
        File file = new File("E:\\demo1");
        //public boolean mkdir() 创建由此抽象路径名命名的目录,如果目标文件夹已经存在,就不创建了,返回false
        System.out.println(file.mkdir());
        //public boolean createNewFile()当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。
        try {
            System.out.println(file.createNewFile());
        } catch (IOException e) {
            e.printStackTrace();
        }

        //需求2:我想在F盘下面的demo2文件夹中创建一个文件b.txt
        //将目标文件封装成File对象
        File file1 = new File("E://demo1", "a.txt");
        try {
            System.out.println(file1.createNewFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //public boolean mkdirs() 创建多级文件夹
        File file2 = new File("E:\\demo1\\demo2\\demo3\\demo4");
        System.out.println(file2.mkdirs());
        //注意1:要想在某个目录下创建文件,前提是该目录必须存在!!
        File file3 = new File("E:\\demo3\\c.txt");
        try {
            System.out.println(file3.createNewFile());//系统找不到指定的路径
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

删除功能:

public boolean delete()

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

public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("E:\\demo1\\a.txt");
        System.out.println(file.delete());
        File file1 = new File("a.txt");
        System.out.println(file1.createNewFile());
        File file2 = new File("aaa\\bbb\\ccc");
        System.out.println(file2.mkdirs());
        //需求:我想删除aaa这个文件夹
        //注意:要删除的目录必须是为空
        File aaa = new File("aaa");
        System.out.println(aaa.delete());

    }
}

重命名功能

public boolean renameTo(File dest)

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

public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        File file = new File("E:\\demo1\\a.txt");
        System.out.println(file.createNewFile());
        File file1 = new File("E:\\demo1\\a.txt");
        File file2 = new File("E:\\demo1\\b.txt");
        System.out.println(file1.renameTo(file2));
    }
}

判断功能

public boolean isDirectory()

public boolean isFile()

public boolean exists()

public boolean canRead()

public boolean canWrite()

public boolean isHidden()

import java.io.File;

public class FileDemo5 {
    public static void main(String[] args) {
        File file = new File("a.txt");

        //public boolean isDirectory() 判断是否是文件夹
        System.out.println(file.isDirectory());
        //public boolean isFile() 判断是否是文件
        System.out.println(file.isFile());
        //public boolean exists() 判断目标文件或者文件夹是否存在
        System.out.println(file.exists());
        //public boolean canRead() 判断是否可读
        System.out.println(file.canRead());

        //public boolean canWrite() 判断是否可写
        System.out.println(file.canWrite());
        //public boolean isHidden() 判断是否隐藏
        System.out.println(file.isHidden());
    }
}

基本获取功能

public String getAbsolutePath()

public String getPath()

public String getName()

public long length()

public long lastModified()

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo6 {
    public static void main(String[] args) {
        File file = new File("a.txt");
        //public String getAbsolutePath()
        //获取绝对路径,或者说完整路径
        System.out.println(file.getAbsoluteFile());
        //public String getPath()
        //获取相对路径
        System.out.println(file.getPath());
        //public String getName()
        //获取名称
        System.out.println(file.getName());
        //public long length()
        //获取的长度是字节数
        System.out.println(file.length());
        //public long lastModified()
        //1645064059299  精确到毫秒
        //返回的是一个时间戳就是这个软件从开发完成运行开始到刚才创建文件的时间
        System.out.println(file.lastModified());
        //java将时间戳与日期进行转换
        //Date(long date)
        //分配一个 Date对象,并将其初始化为表示自称为“时代”的标准基准时间以后的指定毫秒数,即1970年1月1日00:00:00 GMT。
        Date date = new Date(file.lastModified());
        System.out.println(date);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(date);
        System.out.println(format);


    }
}

高级获取功能 public String[] list() public File[] listFiles()

import java.io.File;

public class FileDemo7 {
    public static void main(String[] args) {
        File file = new File("E:\\demo1");
        //public String[] list()
        //获取指定目录下的所有文件和文件夹的名称组成的数组
        String[] list = file.list();
        for (String s:list){
            System.out.println(s);
        }
        System.out.println("============================");
        //public File[] listFiles()
        //获取指定目录下的所有文件和文件夹形成的File对象数组
        File[] files = file.listFiles();
        for (File f:files){
            System.out.println(f);
        }
    }
}
结果:
b.txt
demo2
============================
E:\demo1\b.txt
E:\demo1\demo2

需求:判断D盘下面有没有.jpg后的文件,如果有,就输出此文件名称

1、将D盘根目录封装成一个File对象

2、获取该目录下所有的文件或者文件夹组成的File对象数组

3、遍历File数组,得到每一个File对象,然后判断是否是文件

是:继续判断是否以.jpg后缀

是:输出名称

不是:不管他

不是:不管他

import java.io.File;

public class FileDemo8 {
    public static void main(String[] args) {
        File file = new File("D:\\");
        File[] files = file.listFiles();
        for (File s:files){
            if (s.isFile()){
                if (s.getName().endsWith(".jpg")){
                    System.out.println(s.getName());
                }
            }
        }
    }
}

判断D盘下面有没有.jpg后的文件,如果有,就输出此文件名称

1、先获取所有的文件和文件夹,然后在遍历的时候,再去判断是否是文件,是否是.jpg后缀的,最后再将满足条件的文件过滤出来获取到名称。

2、在获取的时候,获取到的数据就是满足条件的,我们直接输出就可以了。

文件名称过滤器的实现思想及代码

public String[] list(FilenameFilter filter)

public File[] listFiles(FilenameFilter filter)

import java.io.File;
import java.io.FilenameFilter;

public class FileDemo9 {
    public static void main(String[] args) {
//创建对象
        File file = new File("D:\\");
        //public String[] list(FilenameFilter filter)
       String[] list= file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
//                return false;
                //通过测试发现,目录下的文件或者文件夹该不该获取到,却决于这里的返回值
                //true,就获取到加到数组,如果是false,就不获取,不加到数组中
                File file1 = new File(dir, name);
                boolean file2 = file1.isFile();
                boolean b = name.endsWith(".jpg");
                return file2&&b;
            }
        });
        for (String s: list){
            System.out.println(s);
        }
    }
}结果:
a.jpg.jpg
import java.io.File;
import java.io.FilenameFilter;

public class FileDemo9 {
    public static void main(String[] args) {
//创建对象
        File file = new File("D:\\");
        //public String[] list(FilenameFilter filter)
       String[] list= file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
//                return false;
                //通过测试发现,目录下的文件或者文件夹该不该获取到,却决于这里的返回值
                //true,就获取到加到数组,如果是false,就不获取,不加到数组中
//                System.out.println(dir);
//          System.out.println(name);
                File file1 = new File(dir, name);
                boolean file2 = file1.isFile();
                boolean b = name.endsWith(".jpg");
                return file2&&b;
            }
        });
        for (String s: list){
            System.out.println(s);
        }
    }
}
结果:
a.jpg.jpg

递归:方法定义中调用方法本身的现象

Math.max(Math.max(a,b),c) 这样的现象仅仅是方法的嵌套不是方法的递归使用

举例:

1、从前有座山,山里有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事的内容是:

从前有座山,山里有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事的内容是:

从前有座山,山里有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事的内容是:

...

庙倒了,老和尚圆寂了。

2、学习大数据 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃 -- 挣学费:

学习大数据 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃 -- 挣学费:

学习大数据 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃 -- 挣学费:

...

娶不到媳妇,生不了娃。

递归的注意事项:

1、递归一定要有一个出口(结束条件),否则就成了死递归

2、递归的次数不能太多,否则会造成,栈内存溢出

3、构造方法不能发生递归

public class DiGuiDemo1 {
    //死递归
    public void show(){
        show();
    }
}

需求:用代码求出实现5的阶乘 5! = 5*4*3*2*1 = 5*4! = 5*4*3! = 5*4*3*2! = 5*4*3*2*1!

1、用循环解决

2、用递归解决

public class DiGuiDemo2 {
    public static void main(String[] args) {
//        int i=1;
//        for (int x=2;x<=5;x++){
//            i=i*x;
//        }
//        System.out.println("5的阶乘是:" + i);
//    }
        /**
         * 递归方法的前提:
         *  返回值类型:int
         *  参数列表:int i
         *
         *  出口条件:
         *    if(i==1){return 1}
         *
         *  递归主体逻辑:
         *     if(i!=1){
         *         return i*diGui(i-1);
         *     }
         */
        System.out.println(diGui(5));
    }

    public static int diGui(int i) {
        if (i == 1) {
            return 1;
        } else {
            return i * diGui(i - 1);
        }
    }
}

不死神兔案例。

假设有一对兔子,从出生的第三个月开始,每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子。

假设所有的兔子都不会死。问题:二十个月后,兔子的对数是多少?

找规律:

月份 兔子的对数

第一个月 1

第二个月 1

第三个月 2

第四个月 3

第五个月 5

第六个月 8

...

由此课件,兔子的对数的数据是:

1,1,2,3,5,8,13,21,34...

规律:

1、从第三项开始,每一项都是前两项之和

2、说明前两项的数据是已知的

怎么去实现呢?

1、数组实现

2、基本变量实现

3、递归实现

定义两个变量为相邻的数据

第1个相邻的数据: a=1,b=1

第2个相邻的数据: a=1,b=2

第3个相邻的数据: a=2,b=3

第4个相邻的数据: a=3,b=5

规律:下一次相邻的数据,a的值是上一次b的值,b的值是上一次相邻数据的和a+b

public class DiGuiDemo3 {
    public static void main(String[] args) {
        //用数组实现
        int[] arr = new int[20];
        arr[0]=1;
        arr[1]=1;
        for (int i=2;i< arr.length;i++){
            arr[i]=arr[i-2]+arr[i-1];
        }
        System.out.println("第20个月后的兔子对数为:" + arr[19]);
        System.out.println("=============================");
        //基本变量实现
        //下一次相邻的数据,a的值是上一次b的值,b的值是上一次相邻数据的和a+b
        int a=1;
        int b=1;
    for (int i=1;i<=18;i++){
        int temp=a;
        a=b;
        b=temp+b;
    }
        System.out.println(Fibonacc(20));

    }
    /**
     * 返回值类型:int
     * 参数列表:int i 20
     * <p>
     * 出口条件:第一个月是1,第二个月也是1
     * 递归的条件:从第三个月开始,每一个月的值是前两个月之和
     */
    public static int Fibonacc(int i){
        //第一个月是1,第二个月也是1
        if (i==1||i==2){
            return 1;
        }else {
            //从第三个月开始,每一个月的值是前两个月之和
            return Fibonacc(i-1)+Fibonacc(i-2);
        }
    }
}
结果:
第20个月后的兔子对数为:6765
=============================
6765

遍历指定目录下所有的指定后缀名文件名称 E:\数加科技\十五期

分析:

1、将目录封装成File对象

2、获取该目录下所有的File对象组成的数组

3、遍历数组得到每一个File对象

4、判断得到的File对象是一个文件还是一个文件夹

1、如果他是一个文件夹,回到第二步

2、如果他是一个文件,判断文件名称是否以.java后缀

如果是,输出

不是,跳过

import java.io.File;

public class DiGuiDemo4 {
    public static void main(String[] args) {
        File file = new File("E:\\JAVA xm");
        getJavaFile(file);
    }

    public static void getJavaFile(File file) {
        //获取该目录下所有的File对象组成的数组
        File[] files = file.listFiles();

        //遍历数组得到每一个File对象
        for (File f : files) {
            if (f.isDirectory()) {
                getJavaFile(f);
            } else {
                //判断文件名称是否以.java后缀
                if (f.getName().endsWith(".java")) {
                    //如果是,输出
                    System.out.println(f.getName());
                }
            }
        }
    }
}

递归删除带内容的目录

分析:

1、获取File对象

2、获取该目录下所有的文件和文件夹组成的File对象数组

3、遍历数组得到每一个File对象

4、判断这个File对象是否是文件夹

是:返回第二步

不是:直接删除

import java.io.File;

public class DiGuiDemo5 {
    public static void main(String[] args) {
        File file = new File("E:\\demo1");
        deteleFile(file);
    }
    public static void deteleFile(File file){
        //获取该目录下所有的文件和文件夹组成的File对象数组
        File[] files = file.listFiles();
if (file!=null){
    //遍历数组得到每一个File对象
    for (File f:files){
        //判断这个File对象是否是文件夹
        if (f.isDirectory()){
            deteleFile(f);
        }else {
            System.out.println(f.getName() + "---" + f.delete());
        }
    }
    System.out.println(file.getName() + "---" + file.delete());
}
    }
}
结果:
b.txt---true
demo4---true
demo3---true
demo2---true
demo1---true

IO流的分类:

流向:

输入流 读取数据

输出流 写出数据

数据类型:

字节流

字节输入流 读取数据 InputStream

字节输出流 写出数据 OutputStream

字符流

字符输入流 读取数据 Reader

字符输出流 写出数据 Writer

需求:往a.txt文件中写入一句话:"大数据,yyds"

分析:

1、由于是对文本文件进行操作的,最好是用字符流来做,但是,今天重点讲解字节流,字符流是建立在字节流基础之上诞生的

现在就用字节流实现

2、我们要往文件中写一句话,要用到输出流,这里用的是字节输出流

通过上面的分析,最终锁定OutputStream

观察API后发现,OutputStream是一个抽象类,不能被直接实例化

所以我们需要找一个具体实现子类来实例化

FileOutputStream:

构造方法:

FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。

FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。

字节输出流的操作步骤:

1、创建字节输出流对象

2、调用方法,写数据

3、释放资源

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FileOutputStreamDemo1 {
    public static void main(String[] args) throws IOException {
        //创建字节流输出对象
        //FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
//        File file = new File("b.txt");
//        //如果目标文件不存在,自动创建
//        FileOutputStream fileOutputStream = new FileOutputStream(file);
        FileOutputStream fileOutputStream = new FileOutputStream("c.txt");
        System.out.println(fileOutputStream);
        fileOutputStream.write("sjd,hfhf".getBytes());
        fileOutputStream.close();
        fileOutputStream.write("djks".getBytes());//会报错无法继续写入
    }
}

字节输出流写数据的几种方法:

public void write(int b)

public void write(byte[] b)

public void write(byte[] b,int off,int len)

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

public class FileOutoutStreamDemo2 {
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
        FileOutputStream fileOutputStream = new FileOutputStream("d.txt");
        //public void write(int b)
        //97,底层存储的二进制,97对应的ASCII码的字符是a
        fileOutputStream.write(97);
        fileOutputStream.write(48);
        fileOutputStream.write(65);
        //public void write(byte[] b)
        byte[] bytes={45,89,98,74};
        fileOutputStream.write(bytes);
        //public void write(byte[] b,int off,int len)
        //从位于偏移量 off的指定字节数组写入 len字节到该文件输出流。
        fileOutputStream.write(bytes,1,3);
    }
}
文件里的结果:
a0A-YbJYbJ

1、如何实现换行呢?

要想知道为什么没有实现换行?因为我们只写入了数据的字节,并没有写入换行符

如何实现呢?在写字节的时候,添加一个换行符,注意:不同的系统,换行符不一定一样

Mac: \r

Windows: \r\n

Linux: \n

2、如何实现追加呢?

import java.io.FileOutputStream;

public class FileOutputStreamDemo3 {
    public static void main(String[] args) throws Exception {
//        FileOutputStream fileOutputStream = new FileOutputStream("e.txt");
//        fileOutputStream.write("djksj".getBytes());
//        fileOutputStream.write("\r\n".getBytes());
//        fileOutputStream.write("dld".getBytes());
        //FileOutputStream(String name, boolean append)
        //创建文件输出流以指定的名称写入文件。
        //true表示的是可以追加写入数据
        FileOutputStream fileOutputStream1 = new FileOutputStream("e.txt",true);
        fileOutputStream1.write("\r\n今天下雪了\r\n".getBytes());
//        fos.write("\r\n".getBytes());
       fileOutputStream1.write("但是没有看到积雪".getBytes());
       fileOutputStream1.close();
    }
}
文件里的结果:
djksj
dld
今天下雪了
但是没有看到积雪

上一篇:图片链接hover移动的解决方案分析


下一篇:JavaSE笔记