4.3.2 File文件类

本文详细介绍了Java中的File类,包括创建File对象、常用方法如判断文件存在、创建与删除文件/目录,以及使用list()和listFiles()方法展示文件列表,特别是结合FilenameFilter和FileFilter进行文件过滤。示例代码展示了如何根据正则表达式筛选文件名。


1.概述

file文件类主要解决文件或者是文件夹的路径问题,而不是直接解决文件的问题,其命名有些许误导的成分在里面;

封装一个磁盘路径字符串,对这个路径可以执行一次操作,其路径字符串可以封装文件路径、文件夹路径、不存在的路径。

2.创建对象

File类的构造函数有以下几种:

  1. File(String pathname)
  2. File(String parent, String child)
  3. File(File parent, String child)
  4. File(URI uri)

使用构造函数创建的file对象表示一个路径,指向我们的目标文件或文件夹;

File(String pathname)通过将给定路径名字符串转换为抽象路径名来创建一个新的File实例,例如:
- File path = new File("."); //表示当前目录
- File path = new File(“D:/abc/a.txt”); //表示Windows下D盘中的abc文件夹中的a.txt文件
- File path = new File(“D:/abc”,”a.txt”); //表示Windows下D盘中的abc文件夹中的a.txt文件
- File path = new File(new File("."),"bin"); //表示当前目录下的bin文件或者文件夹

但是要注意的是,在java中\是特殊符号,要对其进行转义,所以在java代码中需要使用\对其进行转义;

3.常用方法

在这里插入图片描述

package partThree;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

/* 本类用于测试文件类File*/
public class TestFile {
    public static void main(String[] args) throws IOException {
        //1.创建file类的对象
        /* 1.ready目录与1.txt需要自己手动创建
         *  2.File需要导包:import java.io.File
         *  3.路径是String类型,必须写正确,不然找不到文件
         *  4.完整的文件名是包含俩部分,文件名+后缀名*/
        File file = new File("E:\\ready\\1.txt");

        //2.测试File中的常用方法
        System.out.println("文件的字节量为:"+file.length()); //3.获取文件的字节量
        System.out.println("判断文件是否存在:"+file.exists()); //4.判断文件是否存在
        System.out.println("判断是否为文件:"+file.isFile()); //判断是否为文件
        System.out.println("判断是否为文件夹:"+file.isDirectory()); //判断是否为文件夹
        System.out.println("获取文件名:"+file.getName()); // 1.txt获取文件名
        System.out.println("获取父级路径:"+file.getParent()); // E:\ready 获取父级路径
        System.out.println("获取带盘符的完整(绝对)路径:"+file.getAbsolutePath()); //E:\ready\1.txt 获取带盘符的完整(绝对)路径


        //2.2 测试创建与删除
        /* new只会在内存中创建一个File类型的对象
         * 并不会帮你在磁盘中创建一个真实存在的2.txt文件*/
        file = new File("D:\\ready\\2.txt");

        /*创建一个之前不存在的2.txt文件,如果创建成功,会返回true
         *  如果指定创建的文件的路径不对,会抛出异常:java.io.Excepyion
         *  所以需要提前处理这个问题,我们暂时选择在main()上抛出
         *  这个io异常是目前我们遇到的强制要求必须预先去处理的异常
         *  如果不处理,不能通过编译,方法的调用会报错
         * 会报错,文件路劲异常,就不能创建文件,直接throws,后续会学习如何解决*/
        System.out.println("创建之前不存在的文件:"+file.createNewFile());  //创建之前不存在的文件

        file = new File("E:\ready\\m");
        System.out.println("创建之前不存在的单层文件夹:"+file.mkdir()); //创建之前不存在的单层文件夹

        file = new File("E:\ready\\a\\b\\c");
        System.out.println("创建之前不存在的多层文件夹:"+file.mkdir()); //创建之前不存在的多层文件夹

        System.out.println("删除文件或者空文件夹:"+file.delete());//c被删除,删除文件或者空文件夹
        file  = new File("D:\\ready\\a");
        System.out.println("删除非空文件夹:"+file.delete());//false,因为a目录里还有b目录
        file  = new File("D:\\ready\\2.txt");
        System.out.println("删除文件或者空文件夹:"+file.delete());//true,删除2.txt文件成功

        //2.3 测试展示文件列表
        file = new File("D:\\ready");
        String[] listName = file.list();
        System.out.println("展示文件列表:"+Arrays.toString(listName));
        /* 这句话会报错,因为这是一个String[],所以数组中每个元素都是String类型的
         * 那么只能用String类中的方法,而isDirectory是file类中的方法*/
        // System.out.println(list[0].isDirectory);

        File[] fs = file.listFiles(); // 常用的是此方法
        System.out.println("展示文件列表:"+Arrays.toString(fs));
        System.out.println("展示文件列表:"+fs[0].length());

    }
}

4. 文件列表展示方法详解

4.1 list方法

list()方法会返回一个字符数组,将指定路径下的文件或文件夹名字存储到String数组中。因为其返回的是一个String类型的数组,所以它也就只是一个名字而已(后面要讲到的listFiles()及其重载方法则不同,它们返回的是File类型的对象,所以具有其全部的属性和方法)。有以下两种重载方式:

  1. String[] list()
  2. String[] list(FilenameFilter filter)

4.1.1 String[] list()

package partThree;

import org.junit.Test;
import java.io.File;

public class TestFileList {
    /*
     * File类的构造函数有以下几种:
     * 1、File(File parent, String child);
     * 2、File(String pathname)
     * 3、File(String parent, String child)
     * 4、File(URI uri)
     */
    @Test
    public void testFile1(){
        //1、new File(".")构建的是当前目录的路径
        File file = new File(".");
        String[] list = file.list();
        for(String itemName : list){
            System.out.println(itemName);
        }

        //2、new File("D:\\ready")利用绝对路径构建D盘下的ready目录路径
        System.out.println("----------------------------------");
        file = new File("D:\\ready");
        list = file.list();
        for(String itemName : list){
            System.out.println(itemName);
        }

        //3、new File(new File("."),"src")表示当前目录下的src目录
        System.out.println("----------------------------------");
        file = new File(new File("."),"src");
        list = file.list();//列出当前程序所在位置bin目录下的所有文件或者是文件夹
        for(String itemName : list){
            System.out.println(itemName);
        }
    }
}

运行结果如下:
在这里插入图片描述

4.1.2 String[] list(FilenameFilter filter)

FilenameFilter filter是一个目录过滤器。list(FilenameFilter filter)方法会选择符合条件的文件或文件夹。为了能理解这个函数的工作原理,下面列出了其源码(这个是Java类库中的源码,注释自己添加的):

public String[] list(FilenameFilter filter) {  
        String names[] = list();  //首先调用list()方法,获取指定目录下的全文件(夹)名字
        if ((names == null) || (filter == null)) {//这里判断是否有filter过滤条件,如果没有过滤条件则直接返回获取到的文件(夹)名字  
            return names;  
        }  
        ArrayList v = new ArrayList();  //创建一个新的ArrayList数组来保存一会获取到的文件(夹)名字  
        for (int i = 0 ; i < names.length ; i++) { //有过滤条件的话,遍历names[]数组中的所有文件(夹)名字  
            if (filter.accept(this, names[i])) {   //如果accept()方法返回真,则添加到ArrayList中
                v.add(names[i]);  
            }  
        }  
        return (String[])(v.toArray(new String[v.size()])); //将ArrayList转换成String[]类型返回
     }  

list(FilenameFilter filter)方法源码可以看出,list(FilenameFilter filter)方法保存的是那些能够使filter.accept()方法返回true的文件名。而从filter.accept(this, names[i]);就可以看出,这也是FilenameFilter中的方法。继续往上追溯FilenameFilter的源代码如下:

public  interface FilenameFilter {  
    /** 
     * Tests if a specified file should be included in a file list. 
     * 
     * @param   dir    the directory in which the file was found. 
     * @param   name   the name of the file. 
     * @return  <code>true</code> if and only if the name should be 
     * included in the file list; <code>false</code> otherwise. 
     */  
    boolean accept(File dir, String name);  
}  

我们可以看出FilenameFilter 是一个接口,也就是说此代码的逻辑为:

list(FilenameFilter filter)方法 --------->调用了-------> filter对象中的accept(File dir, String name)方法 ------> FilenameFilter是一个接口

accept()方法会返回一个boolean类型的值,list()方法会根据这个返回值来决定是不是要将某个名字添加到返回列表中。所以,我们要在accept()方法中定义好挑选条件,由于是字符的选取,所以我们可以选择正则表达式。

也就是说,要使用list(FilenameFilter filter)方法就必须实现FilenameFilter接口accept方法由我们自己定义,所以你想要让什么样的文件名能够使得accept方法返回ture(等价的就是你想要什么样的文件名能够被list方法返回)取决于自定义的正则表达式。

接下来我们来完成使用list(FilenameFilter filter)方法的案例:

package partThree;

import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
import org.junit.Test;

public class TestFileList2 {
    /*
     *一、采用实现接口的方式
     *  1.
     *  2.使用Pattern.compile方法对正则表达式regax进行编译
     *  3.重写FilenameFilter类中未实现的accept方法
     *    在重写的方法中使用Pattern.matcher方法匹配字符串,并返回其实例进行matches()的全局匹配
     */
    class FileNameFilterImplement implements FilenameFilter {
        private Pattern pattern;

        public FileNameFilterImplement(String regex) {
            pattern = Pattern.compile(regex);
        }

        @Override
        public boolean accept(File dir, String name) {
            //boolean result = pattern.matcher(name).matches();
            boolean result = pattern.matcher(name).matches();
            return result;
        }
    }
    /*
     * 二、采用匿名内部类的方式。
     * 不用implements的方式来实现接口,但是定义一个静态方法,此静态方法返回一个FilenameFilter对象,
     * 本来正常的语句是return new FilenameFilter();但是在语句结束之前,我们使用匿名内部类的方式进行方法的调用
     * 在内部类中,使用Pattern.compile方法对正则表达式regax进行编译
     * 并且重写FilenameFilter类中未实现的accept方法
     */
    static class FileNameFilterInner{
        public static FilenameFilter filenameFilter(final String regex){
            return new FilenameFilter(){
                private Pattern pattern = Pattern.compile(regex);

                @Override
                public boolean accept(File dir, String name) {
                    return pattern.matcher(name).matches();
                }
            };
        }
    }


    @Test
    public void test2(){
        System.out.println("------使用用接口实现方式,挑选当前目录下以.开头的文件或文件夹-------");
        //1、使用用接口实现方式,挑选当前目录下以.开头的文件或文件夹,并且打印出来(创建一个类来实现FilenameFilter接口)
        File path = new File(".");
        String[] nameList = path.list(new FileNameFilterImplement("\\..*"));
        for(String itemName : nameList){
            System.out.println(itemName);
        }

        System.out.println("------使用内部类实现方式,挑选当前目录下以o开头的文件或文件夹-------");
        //2、挑选当前目录下以t开头的文件或文件夹,并且打印出来(使用匿名内部类的方式来实现)
        File path2 = new File(".");
        String[] nameList2 = path2.list(FileNameFilterInner.filenameFilter("o.*"));
        for(String itemName : nameList2){
            System.out.println(itemName);
        }

        System.out.println("------使用匿名内部类实现方式,挑选当前目录下以s开头的文件或文件夹-------");
        //3、将匿名内部类利用到极致
        File path3 = new File(".");
        String[] nameList3 = path3.list(new FilenameFilter(){//其实是在第二种方式的基础上精简过来的。
            private Pattern pattern = Pattern.compile("s.*");
            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(name).matches();
            }
        });
        for(String itemName : nameList3){
            System.out.println(itemName);
        }
    }
}

上述内容中涉及到的正则表达式内容将在 4.2 正则表达式 中进行介绍;

4.2 listFile方法

首先,我们可以先查看一下FileFilter接口的源代码:

public interface FileFilter {  
  
    /** 
     * Tests whether or not the specified abstract pathname should be 
     * included in a pathname list. 
     * 
     * @param  pathname  The abstract pathname to be tested 
     * @return  <code>true</code> if and only if <code>pathname</code> 
     *          should be included 
     */  
    boolean accept(File pathname);  
  
}  

我们可以看到,其也是要实现accept方法,只是传入的参数不一样,它是File类型的,既然是这样的话,我们就可以利用此处进行文件相关属性的获取了,例如:

  • 当我们要获取文件夹时
class FileDirectory implements FileFilter{  
    @Override  
    public boolean accept(File pathname) {  
        return pathname.isDirectory();  
    }  
  • 当我们要获取可执行文件时
class FileDirectory implements FileFilter{  
    @Override  
    public boolean accept(File pathname) {  
        return pathname.canExecute();  
    }  

接下来我们可以完成一个案例的演示:

package partThree;

import org.junit.Test;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.regex.Pattern;

public class TestFileList3{

    /*
     * list()和listFiles()方法的区别在于:list()返回的是一个String类型数组,它只是一个数组;
     * 而listFiles()方法返回的是一个File类的引用,它具有类的所有属性和方法。
     *
     * 下面的前三个方法返回File[]类型,第四个返回static File[]类型。
     * 返回类型 : 该路径下所有文件或文件夹的绝对路径(pathname:注意File类型指的是路径,而不是文件)
     * listFiles()
     * listFiles(FileFilter filter)
     * listFiles(FilenameFilter filter)
     * listRoots()
     */
    @Test
    public void test3(){
        System.out.println("-----判断当前目录下的文件是否为文件夹----");
        //1、列出当前目录下的所有文件和文件夹,保存为File类对象的数组,判别其是否为文件夹
        File path = new File(".");
        File[] files = path.listFiles();
        for(File f : files){
            System.out.println(f + " ---> is a Directory? " + f.isDirectory());
        }

        System.out.println("-----挑选出当前目录下的所有文件夹----");
        //2、挑选出当前目录下的所有文件夹
        File path2 = new File(".");
        File[] files2 = path2.listFiles(new FileFilter(){
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        });
        for(File f : files2){
            System.out.println(f);
        }

        System.out.println("-----挑选出当前目录下的所有以s开头的文件夹----");
        //3、挑选出当前目录下的所有以s开头的文件夹
        File path3 = new File(".");
        File[] files3 = path3.listFiles(new FileFilter(){
            @Override
            public boolean accept(File pathname) {
                Pattern pattern = Pattern.compile("s.*");
                return pathname.isDirectory()&&pattern.matcher(pathname.getName()).matches();
            }
        });
        for(File f : files3){
            System.out.println(f);
        }

        System.out.println("-----挑选出当前目录下的所有以.开头的文件夹,并且标明文件属性----");
        //4、挑选出当前目录下以.开头的文件或文件夹,并且在其后部标明f/d标明其为文件或文件夹
        File path4 = new File(".");
        File[] files4 = path4.listFiles(new FilenameFilter(){
            Pattern pattern = Pattern.compile("\\..*");
            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(name).matches();
            }
        });
        for(File f : files4){
            String sfd = (f.isFile()) ? "f" : "d";
            System.out.println(f.getName() + "---->" + sfd);
        }
    }
}

执行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值