File类文件相关操作

一、 概述

File类是文件目录路径名,既可以表示文件,也可以表示文件夹。主要用于文件和目录的创建、查找和删除等操作。

文件(File),可以用来表示操作系统中的任何文件。如:Xxx.txt, Xxx.java, Xxx.avi

  • 目录(Directory): 文件夹
  • 文件路径 文件夹路径

FIle可以表示文件或文件夹的路径, 但是这个文件或者是文件夹可能存在, 也可能不存在

所以Java也提供了对应的方法来进行判断是否存在。

二、file构造方法

public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。  
public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。  

绝对路径 : 从盘符开始, 一直表示到最后的文件或者文件夹。如:/tmp/file/a,/tmp/file/a/a.txt

相对路径 : 相对于某一个文件夹开始, 后面的路径。如:在当前文件夹下创建一个文件

File file = new File("/tmp/file/");
file = new File(file,"b.txt");

三、File的创建方法

// 当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
public boolean createNewFile()
// 创建由此File表示的目录。/单级文件夹,返回是否创建成功
public boolean mkdir()
// 创建由此File表示的目录,包括任何必需但不存在的父目录
// 如:当前在/tmp/file目录下,想要在当前目录下创建/logs/draw目录
// new File(file,"/logs/draw").mkdirs();    
public boolean mkdirs()

举例说明:

File file = new File("C:\\Users\\liguang\\Desktop\\filetest\\one","lalal.txt");
System.out.println("文件的绝对路径是:"+file.getAbsolutePath());
if (!file.exists()){
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
System.out.println("文件的大小是:"+file.length());

判断是否存在这个文件,如果存在,那么直接输出对应的文件大小即可。如果不存在,那么创建文件并输出。

File newFile = new File(fileOne,"hello/world/a");
if (!newFile.exists()){
    // newFile.mkdir();
    newFile.mkdirs();
}

使用mkdir这个方法,无法创建出来对应的文件夹,因为这里有多层,而不是单层;

使用mkdirs这个方法,不管是单层文件夹还是多层文件夹,都可以创建成功。

四、删除方法

public boolean delete() :删除由此File表示的文件或目录。//file.delete())    

特点:

      1. 删除的内容不走回收站
      2. 只能删除空文件件

Demo:

在hello/world/a这层目录下没有文件

File newFile = new File(fileOne,"hello/world/a");
if (!newFile.exists()){
    newFile.mkdirs();
}
newFile.delete();

在进行删除的时候可以发现,删除的只有一层,也就是说只把a的给删除掉了,因为new File代表的就只是a这个文件夹,而不是hello/world/a这一整个目录。

但是如果在hello/world/a这层目录下有文件的话,那么就无法进行成功删除。

File file1 = new File("C:\\Users\\liguang\\Desktop\\filetest\\one\\hello\\world");
System.out.println("删除成功否?"+file1.delete()); // false

也就是说file1所能够表示的对象只是代表了当前的文件夹对象,如果想删除整个文件夹下面的文件,那么首先删除的是文件夹下面的文件,然后再删除文件夹,以此来达到对应的效果。

注意:不能够通过文件的length()==0来判断当前文件夹是一个空的文件夹。在当前windows操作系统下,尽管文件夹下面有文件,而且文件中还存在着对应的数据,但是当前的文件夹大小仍然是0。

代码如下:

File file = new File("C:\\Users\\liguang\\Desktop\\filetest\\one\\hello\\world");
System.out.println("对应的文件大小是:"+file.length());  // 0

尽管world文件夹下面存在着对应的文件,但是文件夹大小任然是0.

public class DiGuiDeleteFile {
    public static void main(String[] args) {
        delete(new File("C:\\Users\\liguang\\Desktop\\filetest\\one\\hello"));
    }

    public static void delete(File file) {
        Objects.requireNonNull(file);
        File[] listFiles = file.listFiles();
        for (File listFile : listFiles) {
            if (listFile.isFile()) {
                listFile.delete();
            } else {
                delete(listFile);
            }
        }
        // 此时此刻再来进行一次遍历删除空的文件即可
        for (File listFile : listFiles) {
            listFile.delete();
        }
    }
}

五、获取功能

// 返回此File的绝对路径名字符串。
public String getAbsolutePath()
// 将此File转换为路径名字符串。 获取构造方法中的路径
public String getPath()
// 返回由此File表示的文件或目录的名称    
public String getName() 
// 返回由此File表示的文件的长度。  (字节个数)不能获取文件夹的长度
public long length()

代码如下所示:

public static void main(String[] args) {
    File fileOne = new File("C:\\Users\\liguang\\Desktop\\filetest\\one");
    // 三个判断方法
    if (fileOne.isDirectory()){
        System.out.println("这个是文件夹");
    }
    if (fileOne.isFile()){
        System.out.println("这个是文件");
    }
    if (fileOne.exists()){
        System.out.println("当前文件所表示的文件或者是文件夹是否存在?"+fileOne.exists());
    }

    System.out.println("获取方法");
    System.out.println("-----------------------------------------------------------");
    // 获取得到路径是一样的效果
    String absolutePath = fileOne.getAbsolutePath();
    System.out.println("当前文件的绝对路径是:"+absolutePath);
    String path = fileOne.getPath();
    System.out.println("当前文件的路径是:"+path);
    String name = fileOne.getName();
    System.out.println("获取得到文件的名称或者是文件夹的文字是:"+name);
    // 获取得到文件的大小,不能够表示文件夹的大小
    long length = fileOne.length();
    System.out.println("文件夹的大小是:"+length);
    // 创建一个文件a.txt
    File file = new File(fileOne,"a.txt");
    long length1 = file.length();
    System.out.println("a.txt文件的大小是:"+length1);
    System.out.println("获取得到a.txt的绝对路径是:"+file.getAbsolutePath());
}

六、判断方法

// 此File表示的文件或目录是否实际存在
public boolean exists() 
// 此File表示的是否为目录    
public boolean isDirectory()
// 此File表示的是否为文件    
public boolean isFile() 

具体的demo可以参考上面的案例。

七、遍历文件夹

获取当前文件夹下一层中,所有的文件和文件夹

String[] list() : 获取该文件夹下所有文件和文件夹的名字
File[] listFiles() : 获取该文件夹下所有文件和文件夹(以File的形式获取)
File[] listFiles(FileFilter) :当前文件夹中的所有文件和文件夹, 都会作为参数执行FileFilter中的accept方法, 
							如果返回true, 文件就存入File数组中; 
							如果返回false, 文件就不存了

代码如下所示:

public static void main(String[] args) {
    File file = new File("C:\\Users\\liguang\\Desktop\\filetest\\one");
    // 列举出来文件夹下面的所有的文件和文件夹(如果是文件夹,里面还有文件,那么只会列举出来文件夹的名称)
    String[] list = file.list();
    for (String s : list) {
        System.out.println("文件或者是文件夹的名称是:"+s);
    }
    System.out.println("--------------------");
    File[] files = file.listFiles();
    for (File file1 : files) {
        if (file1.isFile()){
            System.out.println("文件名称是:"+file1.getName());
        }
    }
    System.out.println("----------------------");
    File[] listFilesFilter = file.listFiles(t -> t.isFile() && t.getName().endsWith("a.txt"));
    for (File file1 : listFilesFilter) {
        System.out.println(file1.getName());
    }
}

八、递归遍历文件夹并输出文件

public class FileDemoThree {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\liguang\\Desktop\\filetest\\one");
        printFileName(file);
    }


    /**
     * 递归输出文件名称
     */
    private static void printFileName(File file){
        if (Objects.nonNull(file)){
            File[] listFiles = file.listFiles();
            for (File listFile : listFiles) {
                if (listFile.isFile()){
                    System.out.println("对应的文件名称是:"+listFile.getName());
                }else {
                    printFileName(listFile);
                }
            }
        }
    }

}

在递归期间的注意事项:

1. 递归必须要有出口
2. 就算有出口, 调用的次数不能过多

九、获取得到类路径下的字节码文件

对应的代码如下所示:

public class ClassScanUtil {

    /**
     * 获取得到指定包下的字节码文件
     *
     * @param specifyPackage
     * @return
     */
    public static List<Class<?>> findClassInPackageBySpecify(String specifyPackage) {
        System.out.println("对应的包是:"+specifyPackage);
        List<Class<?>> resultList = null;
        try {
            Objects.requireNonNull(specifyPackage, "指定包为空");
            String tmpPackage = specifyPackage.replace(".", "/");
            Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(tmpPackage);
            if (resources.hasMoreElements()) {
                URL url = resources.nextElement();
                // 如果是文件类型的,那么应该去查找得到对应的字节码文件
                if ("file".equals(url.getProtocol())) {
                    System.out.println("走到这里来了额");
                    resultList = new ArrayList<>();
                    String path = url.getPath();
                    addClassInPackageBySpecifyPackage(specifyPackage, path, resultList);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultList;
    }

    /**
     * 添加指定文件到其中来
     *
     * @param specifyPackage
     * @param path
     * @param resultList
     */
    private static void addClassInPackageBySpecifyPackage(String specifyPackage, String path, List<Class<?>> resultList) {
        File dir = new File(path);
        if (dir.exists() && dir.isDirectory()) {
            // 获取得到文件夹下面的所有文件和文件夹(根据过滤规则来进行操作)
            File[] listFiles = dir.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    boolean isDirectory = pathname.isDirectory();
                    boolean isClassFile = false;
                    if (pathname.isFile()) {
                        String name = pathname.getName();
                        isClassFile = name.endsWith("class");
                    }
                    return isDirectory || isClassFile;
                }
            });
            // 遍历操作
            for (File listFile : listFiles) {
                // 如果是文件夹,那么应该继续进行遍历
                // 如果是对应的文件,那么立即加入即可
                if (listFile.isDirectory()){
                    addClassInPackageBySpecifyPackage(specifyPackage+"."+listFile.getName(),listFile.getAbsolutePath(),resultList);
                }else {
                    String classFileName = listFile.getName().substring(0, listFile.getName().length() - ".class".length());
                    // 获取得到当前文件的路径,然后获取得到对应的com.guang.servlet.HelloServlet.class
                    // 然后加载包到其中来
                    try {
                        Class<?> aClass = Thread.currentThread().getContextClassLoader().loadClass(specifyPackage + "." + classFileName);
                        resultList.add(aClass);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }


    public static void main(String[] args) {
        try {
            List<Class<?>> classList = findClassInPackageBySpecify("com.guang.servlet");
            classList.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

十、得到路径下的指定文件

/**
 * @Description 找到所有的pdf文件对应的路径即可
 * @Author liguang
 * @Date 2022/03/12/14:17
 */
public class FindPDFFile {
    public static void main(String[] args) {

        List<String> pdfFilePath = new ArrayList<>();
        pdfFilePath = findPDFPathBySpecifyRootpath("E:\\test\\day32_vue", pdfFilePath);
        pdfFilePath.forEach(System.out::println);
    }

    /** 这种使用方式原来是可行的!!!!!!!!very nice!!!!!!!!!
     * 根据执行路径这个这个路径下面的所有的文件后缀是pdf的文件后缀
     * 这里有两种方式可以来进行实现
     *
     * @param rootPath
     * @return
     */
    public static List<String> findPDFPathBySpecifyRootpath(String rootPath, List<String> pdfPathList) {
        File file = new File(rootPath);
        Objects.requireNonNull(file);

        // 只有为true的才会在里面
        File[] pdfs = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() || (pathname.isFile() && pathname.getName().contains("pdf"));
            }
        });
        for (File pdf : pdfs) {
            if (pdf.isFile()){
                pdfPathList.add(pdf.getPath());
            }else {
                findPDFPathBySpecifyRootpath(pdf.getPath(),pdfPathList);
            }
        }
        return pdfPathList;
    }

十一、FilenameFilter和FileFilter区别

Java.io.FilenameFilter是文件名过滤器,用来过滤不符合规格的文件名,并返回合格的文件;

(1)String[] fs = f.list();
(2)File[] fs = f.listFiles();

这两个方法返回f文件下的所有文件或目录;

FilenameFilter和FileFilter用来把符合要求的文件或目录返回;

当列出指定文件夹下面的所有的文件或者是目录的时候,返回的值也是不同的。String[]返回的是文件所在路径的全限定路径,而File[]返回的是当前文件夹下的文件或者文件夹的对象;

注:当我们需要对不满足条件的文件或者是文件夹需要过滤掉筛选的时候,那么可以使用过滤掉一些文件来进行操作。

可以看下二者的结构:

/**
* 实现此接口的类的实例用于过滤文件名。 这些实例用于过滤类 File 的 list 方法中的目录列表
*/
public interface FilenameFilter {
    /**
     * 测试指定文件是否应包含在文件列表中。
     *
     * @param   dir     找到文件的目录
     * @param   name    文件的名字
     * @return  当且仅当名称应包含在文件列表中时为 true; 否则为假。
     */
    boolean accept(File dir, String name);
}

对应的案例实操:

        File[] pdfs = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                /**
                 * 对应的文件是:E:\test\day32_vue,对应的name是:代码
                 * 对应的文件是:E:\test\day32_vue,对应的name是:画图
                 * 对应的文件是:E:\test\day32_vue,对应的name是:笔记
                 * 对应的文件是:E:\test\day32_vue,对应的name是:资料
                 * 对应的dir是指定的文件夹,name是每个获取得到的文件名称
                 */
                System.out.println("对应的文件是:" + dir + ",对应的name是:" + name);
                // dir永远都是文件的前缀路径!所以这里需要来对其进行过滤掉
                return dir.isDirectory() || name.contains("pdf");
            }

看一下FileFilter类:

// 对于文件名称的过滤
@FunctionalInterface
public interface FileFilter {

    /**
     * 测试指定的抽象路径名是否应包含在路径名列表中
     *
     * @param  pathname  抽象的文件名称
     * @return  当且仅当应该包含路径名时才为真
     */
    boolean accept(File pathname);
}

看一下对应的案例:

// 只有为true的才会在里面
File[] pdfs = file.listFiles(new FileFilter() {
    @Override
    public boolean accept(File pathname) {
        return pathname.isDirectory() || (pathname.isFile() && pathname.getName().contains("pdf"));
    }
});

十二、总结

posted @ 2022-02-09 18:54  写的代码很烂  阅读(328)  评论(0编辑  收藏  举报