Bootstrap

【Java】File的成员方法

一、总述

File 的成员方法非常的多

有跟判断获取相关的

image-20240502124100282

还有跟创建、删除相关的

image-20240502131201617

还有跟遍历文件夹相关的

当然遍历文件夹有很多的方法,其中需要我们掌握的只有一个就可以了。

image-20240502135227760

方法有点多,但是不要慌,已经帮大家分好类了,而且方法很简单,不要背,通过IDEA的自动提示功能能想起来就行了。

先来看第一类:判断和获取相关的方法,其实这些方法你猜也能猜到,我们之前曾经说过,File对象 表示的路径可以是存在的,也可以是不存在的,因此肯定会有一个方法去判断是否存在,因此就有 exists()

如果存在,它是文件还是文件夹呢?肯定也会有方法进行判断:isDirectory()isFile(),这就是三个判断的方法。

再来看获取的方法,文件、文件夹有什么东西值得你去获取呢?大小、路径、文件名、修改时间。


二、判断方法

获取文件路径的两种方式。

image-20240502124917074

image-20240502140617877
//1.对一个文件的路径进行判断
File f1 = new File("D:\\aaa\\a.txt");
System.out.println(f1.isDirectory());//false。是不是文件夹,如果是文件夹返回true,如果是文件返回false
System.out.println(f1.isFile());//true。是不是文件
System.out.println(f1.exists());//true。判断文件夹 / 文件是否存在
System.out.println("--------------------------------------");
//2.对一个文件夹的路径进行判断
File f2 = new File("D:\\aaa\\bbb");
System.out.println(f2.isDirectory());//true
System.out.println(f2.isFile());//false
System.out.println(f2.exists());//true
System.out.println("--------------------------------------");
//3.对一个不存在的路径进行判断
File f3 = new File("D:\\aaa\\c.txt");
System.out.println(f3.isDirectory());//false
System.out.println(f3.isFile());//false
System.out.println(f3.exists());//false

三、获取方法

1)public long length()

返回文件的大小,单位是 字节数量

查看多个文件的大小

image-20240502154244583

查看单个文件的大小

image-20240502125032978
File f1 = new File("D:\\aaa\\a.txt");
long len = f1.length();
System.out.println(len);//12

但如果调用者不是文件,而是文件夹呢?

细节1:这个方法只能获取文件的大小,单位是字节。

如果单位我们要是M、G,可以不断的除以1024。例如除以一次 1024 那就是 kb,除以两次 1024 那就是 M

细节2:这个方法无法获取文件夹的大小。

因为调用 length() 的时候,不同的操作系统可能是不一样的,我的操作系统返回的是0,有的人的操作系统返回的是4096,不管是返回什么,这个结果都是不对的,这个方法是无法获取文件夹的大小的。

如果我们要获取一个文件夹的大小,需要把这个文件夹里面所有的文件大小都累加在一起。

File f2 = new File("D:\\aaa\\bbb"); //注意bbb文件夹里是有东西的
long len2 = f2.length();
System.out.println(len2);//0

2)public String getAbsolutePath()

返回文件的绝对路径

File f3 = new File("D:\\aaa\\a.txt");
String path1 = f3.getAbsolutePath();
System.out.println(path1); // D:\aaa\a.txt

有的同学会说:你将参数返回给我有什么意义。

别急,在当前模块下再新建 a.txt,在创建 File对象 的时候写相对路径,相对路径是相对于当前项目而言的。

例如以下代码,它会先在当前项目下先找 myFile,再去找 a.txt

但如果你没有写 myFile,那么这个 a.txt 就是直接在项目下的,而不是在模块里面的了。

File f4 = new File("myFile\\a.txt");
String path2 = f4.getAbsolutePath();
System.out.println(path2); // C:\Users\alienware\IdeaProjects\basic-code\myFile\a.txt

3)public String getPath()

返回定义文件时使用的路径,即当你在创建 File对象 的时候,括号里面写的是什么,那么返回的就是什么。

File f5 = new File("D:\\aaa\\a.txt");
String path3 = f5.getPath();
System.out.println(path3);//D:\aaa\a.txt

File f6 = new File("myFile\\a.txt");
String path4 = f6.getPath();
System.out.println(path4);//myFile\a.txt

4)public String getName()

返回文件的名称,带后缀

File f7 = new File("D:\\aaa\\a.txt");
String name1 = f7.getName();
//a.txt:
//      a 文件名
//      txt 后缀名、扩展名
System.out.println(name1); // a.txt

下面将路径改为 bbb文件夹

File f8 = new File("D:\\aaa\\bbb");
String name2 = f8.getName();
// 文件夹:返回的就是文件夹的名字
System.out.println(name2);//bbb

5)public long lastModified()

返回文件的最后修改时间,返回时间的毫秒值,类型为 long

File f9 = new File("D:\\aaa\\a.txt");
long time = f9.lastModified();
System.out.println(time); // 1667380952425

课堂练习

//如何把时间的毫秒值变成字符串表示的时间呢?
//格式为:yyyy年MM月dd日 HH:mm:ss

四、创建方法

计算机里面要么是文件,要么是文件夹,没有其他的了。

因此创建无非是两种:创建文件、创建文件夹。

1)public boolean createNewFile()

返回值表示:当前文件是否创建成功。

File f1 = new File("D:\\aaa\\c.txt"); // 要注意,此时在aaa文件夹中是没有c.txt文件的
boolean b = f1.createNewFile(); // 调用createNewFile()将文件创建出来
System.out.println(b);//true

代码写完后发现,它有一个红色波浪线

image-20240502131926814

alt + 回车,在IDEA中给出了两种异常的解决方案

1、抛出

2、用 try-catch 包裹

image-20240502132005253

扩展:如果这个路径是存在它,它会报错吗?

File f1 = new File("D:\\aaa\\a.txt"); // a.txt已存在
boolean b = f1.createNewFile();
System.out.println(b);//false

程序运行结束,并没有报错

细节1:如果当前路径表示的文件是不存在的,则创建成功,方法返回true
      如果当前路径表示的文件是存在的,则创建失败,方法返回false

细节2:如果父级路径是不存在的,那么方法会有IOException异常
File f1 = new File("D:\\aaa\\ddd\\a.txt"); // aaa文件夹是存在的,ddd文件夹是不存在的
boolean b = f1.createNewFile();
System.out.println(b);

程序运行完毕,会发现直接报错。

image-20240502132809931
细节3:createNewFile方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件
    由此可见,文件是可以没有后缀名的。
File f1 = new File("D:\\aaa\\ddd");
boolean b = f1.createNewFile();
System.out.println(b);//true

如下图,这个文件也是可以使用记事本打开的。

image-20240502132942804

2)public boolean mkdir()

mk:make;dir:directory,文件夹还有一个称呼:目录,因此以后我们说 创建一个目录,其实就表示创建一个文件夹的意思。

返回值表示:当前文件夹是否创建成功。

Windows操作系统 中,路径一定是唯一的,不能重复的,在之前我们已经创建了一个没有后缀的文件 ddd,因此已经不能创建 ddd 文件夹了。

image-20240502133502591
细节1:windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false
File f2 = new File("D:\\aaa\\ddd");
boolean b = f2.mkdir();
System.out.println(b); // false

接下来换个目录创建

File f2 = new File("D:\\aaa\\eee");
boolean b = f2.mkdir();
System.out.println(b); // true

但如果后面有多个文件夹都不存在呢?例如下面代码,只有aaa文件夹存在会发生什么?

细节2:mkdir方法只能创建单级文件夹,无法创建多级文件夹。
File f2 = new File("D:\\aaa\\aaa\\bbb\\ccc");
boolean b = f2.mkdir();
System.out.println(b); // false

3)public boolean mkdirs()

创建多级文件夹,其中包含单级文件夹。

File f3 = new File("D:\\aaa\\ggg");
boolean b = f3.mkdirs();
System.out.println(b);//true

既然 mkdirs() 既能创建单级的,又能创建多级文件夹,那么 mkdir() 岂不是没有用了。

是的,你说的没有错以后它确实没有用了。那为什么我们还要去学习它呢?

因为在 mkdirs() 的底层它会用到 mkdir()

源码:如果我们要创建多级文件夹,首先它会先去判断这个路径是否存在,然后用 mkdir() 创建单级文件夹试一下,如果创建成功了,直接 return true,如果没有创建成功,才会执行自己的逻辑。

image-20240502134125006

因此以后创建文件夹,可以一律使用 mkdirs()


五、删除方法

delete() 默认只能删除文件和空文件夹,delete() 直接删除不走回收站。

public boolean delete() // 删除文件、空文件夹
细节:
    如果删除的是文件,则直接删除,不走回收站,返回true
    如果删除的是空文件夹,则直接删除,不走回收站,返回true
    如果删除的是有内容的文件夹,则删除失败,返回false
//1.创建File对象
File f1 = new File("D:\\aaa\\eee");
//2.删除
boolean b = f1.delete();
System.out.println(b);

六、获取并遍历

获取并遍历 的方法有很多,但是这些方法中只需要重点掌握刚刚学习的空参的 listFiles() 即可,其他的了解一下即可。

1)public File[] listFiles()

接下来学习 File类 中最重要的一个方法:获取并遍历。

获取到当前路径下所有的内容,并将它们放到一个数组中进行返回。

代码示例

//1.创建File对象
File f = new File("D:\\aaa");
//2.listFiles方法
//作用:获取aaa文件夹里面的所有内容,包括文件,包括文件夹,哪怕你是隐藏的,它都能获取。然后把所有的内容放到数组中返回
File[] files = f.listFiles();
for (File file : files) {
    //file依次表示aaa文件夹里面的每一个文件或者文件夹
    System.out.println(file);
}

细节

1、当调用者 File 表示的路径不存在时,返回 null

2、当调用者 File 表示的路径是文件时,返回 null

3、当调用者 File 表示的路径是一个空文件时,回一个长度为0的数组

4、当调用者 File 表示的路径是一个有内容的文件夹时,它会将里面所有的文件和文件夹的路径放在 File数组 中返回

5、当调用者 File 表示的路径是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在 File数组 中返回,包含隐藏文件

6、当调用者 File 表示的路径是需要权限才能访问的文件夹时,返回 null

有很多同学的电脑权限比较高,特别是 C盘,没有权限是进不去的。Java也是一样的,遇到这样的文件夹,用 listFiles() 也无法获取到里面的东西,也会返回一个 null

例如 C:\$Recycle.Bin\S-1-5-18 是一个隐藏的文件夹,表示回收站,这个文件夹我们是没有权限进入的,因此返回 null


2)public static File[] listRoots()

作用:获取系统中所有的盘符

注意,这个方法是 static静态 的,因此需要直接使用 File类名 调用。

这个方法在以后我们会偶尔使用,例如遍历整个硬盘的时候,搜索所有硬盘里面的电影名。

File[] arr = File.listRoots();
System.out.println(Arrays.toString(arr)); // [C:\, D:\, E:\, F:\, G:\]

3)public String[] list()

获取当前该路径下所有内容。

但是它仅仅只能获取名字,如果是文件:文件名+后缀名;文件夹:获取的时文件夹的名字。

这个方法返回的类型不是 File ,而是 String

File f1 = new File("D:\\aaa");
String[] arr2 = f1.list();
for (String s : arr2) {
    System.out.println(s);
}

4)public String[] list(FilenameFilter filter)

利用文件名过滤器获取当前该路径下所有内容。

选中 list方法 往下拉

image-20240502140058500

继续跟进 FilenameFilter,可以发现它是一个接口,而且还是一个函数式接口,因此我们可以写成匿名内部类,也可以写成 Lambda表达式,如果有合适的方法,我们甚至可以用方法引用。

方法返回的同样是 String,里面存储的就是每个文件的绝对路径。

需求:我现在要获取D:\aaa 文件夹里面所有的 txt文件

//accept方法的形参,依次表示aaa文件夹里面每一个文件或者文件夹的路径
//参数一:父级路径
//参数二:子级路径
//返回值:如果返回值为true,就表示当前路径保留,返回到数组中
//        如果返回值为false,就表示当前路径舍弃不要,不会返回到数组中
String[] arr3 = f2.list(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String name) {
        File src = new File(dir,name);
        return src.isFile() && name.endsWith(".txt");
    }
});

就算我们不会这个方法也没关系,使用 listFiles() 也可以实现。

因此在以后我们重点掌握 listFiles() 即可,其他方法了解一下即可。

//1.创建File对象
File f = new File("D:\\aaa");
//2.需求:打印里面所有的txt文件
File[] arr = f.listFiles();
for (File file : arr) {
    //file依次表示aaa文件夹里面每一个文件或者文件夹的路径
    if(file.isFile() && file.getName().endsWith(".txt")){
        System.out.println(file);
    }
}

5)public File[] listFiles(FileFilter filter)

利用文件名过滤器获取当前该路径下所有内容。

只不过它的返回值不是 String[] 而是 File[]

//创建File对象
File f = new File("D:\\aaa");
//调用listFiles(FileFilter filter)
File[] arr1 = f.listFiles(new FileFilter() {
    @Override
    // 参数pathname依次表示文件夹里面的每一个文件或者文件夹
    //返回值:如果返回值为true,就表示当前路径保留,返回到数组中
	//		如果返回值为false,就表示当前路径舍弃不要,不会返回到数组中
    public boolean accept(File pathname) {
        return pathname.isFile() && pathname.getName().endsWith(".txt");
    }
});

6)public File[] listFiles(FilenameFilter filter)

利用文件名过滤器获取当前该路径下所有内容。

public File[] listFiles(FileFilter filter) 的区别是:

  • public File[] listFiles(FileFilter filter) 中接口的形参 pathname 是一个完整的路径
  • public File[] listFiles(FilenameFilter filter) 是将一个大的路径拆开为 父级路径子级路径
//调用listFiles(FilenameFilter filter)
File[] arr2 = f.listFiles(new FilenameFilter() {
    @Override                  
    public boolean accept(File dir, String name) {
        File src = new File(dir, name);
        return src.isFile() && name.endsWith(".txt");
    }
});
System.out.println(Arrays.toString(arr2));
;