🍧 Peach

蜜桃学代码

IO - File、FileFilter 和 FilenameFilter


(一)File - 文件

对文件和目录进行增删改查操作

%%{
  init: {
    'themeVariables': {
         'fontSize': '12px'
       }
    }
}%%
graph TD
T(["File 文件对象"]):::p
T --> A("File类能操作文件本身的属性"):::p
T -.-x B("File对象不能操作文件中的内容"):::g
A --> a("* 查看文件属性#12288;#12288;#12288;
* 创建新文件、文件夹
* 查看父级目录#12288;#12288;#12288;
* 遍历、删除文件夹#12288;"):::lp B -.-> b("需要通过 I/O 的方式来完成"):::lg info("file对象不是真正的文件,
而是堆内存中创建出来的一个对象空间"):::info classDef p fill:#ddaebd classDef b fill:#aab7d2 classDef g fill:#a6ccc3 classDef lp fill:#f4e4e9 classDef lb fill:#d9dfeb classDef lg fill:#ddebe6 classDef info fill:#f6f6f7,color:#5a5a5f,stroke-dasharray: 3 3, stroke-width: 1px click b "https://equnee.github.io/note/Basics/IO/IO_IO/"

① 实现的接口

Serializable, Comparable

② 构造方法

在能够操作目录或文件之前,要先创建一个文件对象,指向目录或文件。

构造方法 说明
(没有无参构造方法)
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新File实例。
File(File parent, String child) 根据parent抽象路径名child路径名字符串创建一个新File实例。
File(String parent, String child) 根据parent路径名字符串child路径名字符串创建一个新File实例。
File(URI uri) 通过将给定的 file:URI 转换为一个抽象路径名来创建一个新的File实例。

③ 常用方法

  • 文件基本属性

    常用方法 说明
    canExecute() 可执行
    canRead() 可读
    canWrite() 可写
    exists() 文件名或路径是否存在
    isHidden() 是否隐藏
    isFile() 判断当前file是否是一个文件
    isDirectory() 判断当前file是否是一个目录
    isAbsolute() 判断File对象所对应的文件或目录是否是绝对路径
    length() 获取文件中字节的个数
    lastModified() 获取文件最后的修改时间(long类型:毫秒值)
  • 文件名

    常用方法 说明 返回值类型
    getName() 获取文件名字(Test.txt String name
    getAbsolutePath() 获取文件的绝对路径(D://test//Test.txt String path
    getPath() 获取文件的完整路径 String path
    renameTo(File dest) 重命名,命名成功返回true Boolean true
  • 创建

    常用方法 说明 返回值类型
    createNewFile() 创建一个文件(需要捕捉IOException) boolean
    mkdir() 创建一个目录 boolean
    mkdirs() 创建所有目录(同时创建多层目录) boolean
    createTempFile(String prefix, String suffix, File directory) 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 File
  • 获取对象

    常用方法 说明 返回值类型
    getParent() 获取当前File的父目录的完整路径 String name
    getParentFile() 获取当前File的父亲file对象 File file
    getAbsoluteFile() 返回此File对象所对应的绝对路径所对应的File对象 File file
    list() 获取当前File对象的所有儿子名字 String[] names
    listFiles() 获取当前File对象的所有子对象(目录或文件) File[] files
    static listRoots() 列出系统所有的根路径。 File[] files
  • 删除

    常用方法 说明 返回值类型
    delete() 彻底删除文件或空目录,无法删除带元素的文件夹 boolean
    deleteOnExit() 删除文件或目录并关闭流操作 boolean
- Demo
package com.equne;

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

public class FileTest
{
public static void main(String[] args) throws IOException {
// 以当前路径来创建一个File对象
File file=new File(".");
// 直接获取文件名,输出一点
System.out.println(file.getName());
// 获取相对路径的父路径可能出错,下面代码输出null
System.out.println(file.getParent());
// 获取绝对路径
System.out.println(file.getAbsoluteFile());
// 获取上一级路径
System.out.println(file.getAbsoluteFile().getParent());

// 在当前路径下创建一个临时文件
File tmpFile=File.createTempFile("aaa", ".txt", file);
// 指定当JVM退出时删除该文件
tmpFile.deleteOnExit();

// 以系统当前时间作为新文件名来创建新文件
File newFile=new File(System.currentTimeMillis() + "");
System.out.println("newFile对象是否存在:" + newFile.exists());
// 以指定newFile对象来创建一个文件
newFile.createNewFile();
// 以newFile对象来创建一个目录,因为newFile已经存在
// 所以下面方法返回false,即无法创建该目录
newFile.mkdir();
// 使用list()方法列出当前路径下的所有文件和路径
String[] fileList=file.list();
System.out.println("====当前路径下所有文件和路径如下====");
for (String fileName : fileList)
{
System.out.println(fileName);
}
// listRoots()静态方法列出所有的磁盘根路径
File[] roots=File.listRoots();
System.out.println("====系统所有根路径如下====");
for (File root : roots)
{
System.out.println(root);
}
}
}

/**
* .
* null
* /Users/equne/Desktop/testJava/Test2/.
* /Users/equne/Desktop/testJava/Test2
* newFile对象是否存在:false
* ====当前路径下所有文件和路径如下====
* Test2.iml
* out
* 1679734377738
* aaa5603141847215609264.txt
* .idea
* src
* ====系统所有根路径如下====
* /
*
*/

(摘自《疯狂Java讲义》)



(二)FileFilter 和 FilenameFilter

接口:快速地按照特定要求找出所有文件

FileFilter 与 FilenameFilter 用于检测文件是否存在。它们都是接口,只需编写的实现类实现它们的函数 accept() 即可 。

接口 区别 方法
FileFilter 提供文件对象的访问方法 boolean accept(File file);
FilenameFilter 按照目录和文件名的方式进行 boolean accept(File directory, String name);

① FileFilter

Demo:搜索特定的文件扩展名

  • ExtensionFilter

    /**
    * 扩展名过滤器
    */
    public class ExtensionFilter implements FileFilter {
    // 🔴 一、定义一个扩展名过滤器类:实现接口 FileFilter

    private String extension; // 扩展名

    // 🔴 二、构造函数中初始化变量extension:待匹配的文件扩展名
    public ExtensionFilter(String extension) {
    this.extension = extension;
    }

    // 🔴 二、接口函数:实现扩展名过滤
    public boolean accept(File file) {
    // 🔹 若为目录:返回false
    if (file.isDirectory()) {
    return false;
    }
    // 取得文件名
    String name = file.getName();
    // 取得扩展名前的符号“.”的下标位置
    int index = name.lastIndexOf(".");
    // 🔹 判断扩展名
    if(index == -1){ // 若没有扩展名:返回false
    return false;
    } else if(index == name.length() - 1){ // 若以点号结尾:返回false
    return false;
    } else{ // 若扩展名相同:返回true
    return this.extension.equals(name.substring(index + 1));
    }
    }
    }
  • TestFile

    /**
    * 测试类:使用上述的ExtensionFilter类来查找 D:/demo 目录下、扩展名为txt的文件列表。
    */
    public class TestFile {

    public static void main(String[] args) {

    File file = new File("D:/demo");
    // 创建一个txt过滤器
    ExtensionFilter txtFilter = new ExtensionFilter("txt");
    // 使用过滤器查找txt文件
    File[] files = file.listFiles(txtFilter);
    // 输出查找的文件列表
    for (int i = 0; i < files.length; i++) {
    System.out.println(files[i].getAbsolutePath());
    }
    }

    }

    // D:\demo\test.txt
    // D:\demo\test2.txt

    若使用 FilenameFilter,结果会让你很难判断到底是目录还是文件。

② FilenameFilter

FilenameFilter 的过滤函数 accept() 直接根据目录和文件名进行过滤,与 FileFilter 相比,多了一个文件名参数通常我们都建议使用 FilenameFilter 类进行文件过滤。

Demo:图片过滤器

  • ImageFilter

    /**
    * 图片过滤器:过滤扩展名为.gif,.jpg,.png的文件
    */
    public class ImageFilter implements FilenameFilter {

    // 🔹 gif类型文件
    public boolean isGif(String filename) {
    if (filename.toLowerCase().endsWith(".gif")) {
    return true;
    } else {
    return false;
    }
    }

    // 🔹 jpg类型文件
    public boolean isJpg(String filename) {
    if (filename.toLowerCase().endsWith(".jpg")) {
    return true;
    } else {
    return false;
    }
    }

    // 🔹 png类型文件
    public boolean isPng(String filename) {
    if (filename.toLowerCase().endsWith(".png")) {
    return true;
    } else {
    return false;
    }
    }

    // 🔴 接口函数:实现扩展名过滤
    public boolean accept(File dir, String filename) {
    return (isGif(filename) || isJpg(filename) || isPng(filename));
    }
    }
  • TestFile

    public class TestFile {
    public static void main(String[] args) {

    // 目录实例
    File file = new File("D:/demo");

    // ---------- FileFilter ------------
    // 创建一个txt过滤器
    ExtensionFilter txtFilter = new ExtensionFilter("txt");
    // 使用过滤器查找txt文件
    File[] files = file.listFiles(txtFilter);
    // 输出查找的文件列表
    for (int i = 0; i < files.length; i++) {
    System.out.println(files[i].getAbsolutePath());
    }

    // --------- FilenameFilter -----------
    // 创建一个图片过滤器
    ImageFilter imageFilter = new ImageFilter();
    // 使用过滤器查找图片文件
    File[] images = file.listFiles(imageFilter);
    // 输出查找的文件列表
    for (int i = 0; i < images.length; i++){
    System.out.println(images[i].getAbsolutePath());
    }
    }
    }

    // D:\demo\a.jpg
    // D:\demo\b.gif

    (摘自:《Java高手真经(编程基础卷)》



(三)*递归 - 遍历文件夹

① 递归

递归

本质:方法的调用 (即自己调用自己,且每次传的参数都不一样)

public class newTestFile{

public void buildTower(int floor){ // 设计一个方法,描述盖宝塔
if(floor>1){
this.buildTower(floor-1);
}

System.out.println("改到第"+ floor + "层啦"); // 自己执行
}
}

内存结构图:
递归内存结构图

② 遍历文件夹

/* 
* 遍历文件夹。参数:file(代表文件或文件夹)
*/
import java.io.File;
public class newTestFile{

public void showFile(File file){

File[] files = File.listFiles();
// 如果在调用前输出,则相反输出
if (files != null && files.length != 0){ // 🔹 非文件 && 非空文件夹
for(File f : files){ // 遍历
this.showFile(); // 🔹 递归
}
}
System.out.println(file.getAbsolutePath());
}
}
  • 删除文件夹file.delete(); // 将上面的例子替换



- end -