14.1.1 概述

  • File 类是 java.IO包下代表与平台无关的文件和目录
  • 在程序中操作文件和目录都可以通过 File 类来完成
  • File 类能新建、删除、重命名文件和目录
  • 在 API 中 File 的解释是文件和目录路径名的抽象表示形式,即 File 类是文件或目录的路径,而不是文件本身
  • 因此 File 类不能直接访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流

File 类代表磁盘或网络中某个文件或目录的路径名称,如:/test/javase/IO/佟test.jpg

但不能直接通过 File 对象读取和写入数据,如果要操作数据,需要 IO 流 File 对象好比是到水库的“路线地址”,要“存取”里面的水到你“家里”,需要“管道”

1563809289418.png

14.1.2 构造方法

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

构造举例

  1. // 方式一:直接传文件路径名
  2. File file1 = new File("files/test.txt");
  3. System.out.println(file1.getName());
  4. // 方式二:父类路径+子类路径
  5. File file2 = new File("files", "test.txt");
  6. System.out.println(file2.getName());
  7. // 方式三:父类抽象对象+子类路径
  8. File file3 = new File(new File("files"), "test.txt");
  9. System.out.println(file3.getName());

小贴士

  1. 一个 File 对象代表硬盘中实际存在的一个文件或者目录
  2. 无论该路径下是否存在文件或者目录,都不影响 File 对象的创建
    // 不存在的文件名
    File file4 = new File("files/test1.txt");
    // 即使文件不存在,也会创建对象且会打印文件名
    System.out.println(file4.getName());
    

14.1.3 常用方法(了解)

获取文件和目录基本信息的方法

  • public String getName() :返回由此 File 表示的文件或目录的名称
  • public long length() :返回由此 File 表示的文件的长度
  • public String getPath() :将此 File 转换为路径名字符串
  • public long lastModified():返回 File 对象对应的文件或目录的最后修改时间(毫秒值)

代码 🌰

import java.io.File;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class TestFile {
    public static void main(String[] args) {
        File f = new File("d:/aaa/bbb.txt");     
        System.out.println("文件构造路径:"+f.getPath());
        System.out.println("文件名称:"+f.getName());
        System.out.println("文件长度:"+f.length()+"字节");
        System.out.println("文件最后修改时间:" + LocalDateTime.ofInstant(Instant.ofEpochMilli(f.lastModified()),ZoneId.of("Asia/Shanghai")));

        File f2 = new File("d:/aaa");     
        System.out.println("目录构造路径:"+f2.getPath());
        System.out.println("目录名称:"+f2.getName());
        System.out.println("目录长度:"+f2.length()+"字节");
        System.out.println("文件最后修改时间:" + LocalDateTime.ofInstant(Instant.ofEpochMilli(f.lastModified()),ZoneId.of("Asia/Shanghai")));
    }
}

输出结果:
文件构造路径:d:\aaa\bbb.java
文件名称:bbb.java
文件长度:636字节
文件最后修改时间:2019-07-23T22:01:32.065

目录构造路径:d:\aaa
目录名称:aaa
目录长度:4096字节
文件最后修改时间:2019-07-23T22:01:32.065

API 中说明:length(),表示文件的长度但是 File 对象是目录,则返回值未指定

各种路径问题

  • public String getPath() :将此 File 转换为路径名字符串
  • public String getAbsolutePath() :返回此 File 的绝对路径名字符串
  • String getCanonicalPath():返回此 File 对象所对应的规范路径名
    public static void main(String[] args) throws IOException {
      // 方式一:直接传文件路径名
      File file1 = new File("files/test.txt");
      System.out.println(file1.getPath());
      System.out.println(file1.getAbsolutePath());
      System.out.println(file1.getCanonicalPath());
    }
    

判断功能的方法

  • public boolean exists() :此 File 表示的文件或目录是否实际存在
  • public boolean isDirectory() :此 File 表示的是否为目录
  • public boolean isFile () :此 File 表示的是否为文件
    public class FileIs {
      public static void main(String[] args) {
          File f = new File("d:\\aaa\\bbb.java");
          File f2 = new File("d:\\aaa");
            // 判断是否存在
          System.out.println("d:\\aaa\\bbb.java 是否存在:"+f.exists());
          System.out.println("d:\\aaa 是否存在:"+f2.exists());
            // 判断是文件还是目录
          System.out.println("d:\\aaa 文件?:"+f2.isFile());
          System.out.println("d:\\aaa 目录?:"+f2.isDirectory());
      }
    }
    输出结果:
    d:\aaa\bbb.java 是否存在:true
    d:\aaa 是否存在:true
    d:\aaa 文件?:false
    d:\aaa 目录?:true
    

如果文件或目录不存在,那么 exists()、isFile() 和 isDirectory() 都是返回 false

创建删除功能的方法

  • public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
  • public boolean delete() :删除由此 File 表示的文件或目录,只能删除空目录
  • public boolean mkdir() :创建由此 File 表示的目录
  • public boolean mkdirs() :创建由此 File 表示的目录,包括任何必需但不存在的父目录

    public class FileCreateDelete {
      public static void main(String[] args) throws IOException {
        // 创建文件
          File newFile = new File("src/com/poloyy/basic_014/files/test1.txt");
          System.out.println("====创建文件");
          System.out.println(newFile.createNewFile());
          System.out.println(newFile.createNewFile());
          System.out.println(newFile.exists());
          System.out.println(newFile.isFile());
          System.out.println(newFile.delete());
          System.out.println(newFile.exists());
    
          // 单级目录
          File newDir = new File("src/com/poloyy/basic_014/files1");
          System.out.println("====创建目录");
          System.out.println(newDir.mkdir());
          System.out.println(newDir.mkdir());
          System.out.println(newDir.exists());
          System.out.println(newDir.isDirectory());
          System.out.println(newDir.delete());
          System.out.println(newDir.exists());
    
          // 多级目录
          File newMoreDir = new File("src/com/poloyy/basic_014/files1/files");
          System.out.println("====创建多级目录");
          System.out.println(newMoreDir.mkdirs());
          System.out.println(newMoreDir.mkdirs());
          System.out.println(newMoreDir.exists());
          System.out.println(newMoreDir.isDirectory());
          System.out.println(newMoreDir.delete());
          System.out.println(newMoreDir.exists());
      }
    }
    

API中说明:delete方法,如果此 File 表示目录,则目录必须为空才能删除

14.1.4 递归实现多级目录操作

  • public String[] list() :返回一个String数组,表示该 File 目录中的所有子文件或目录
  • public File[] listFiles() :返回一个 File 数组,表示该 File 目录中的所有的子文件或目录
  • public File[] listFiles(FileFilter filter):返回所有满足指定过滤器的文件和目录,如果给定 filter 为 null,则接受所有路径名;否则,当且仅当在路径名上调用过滤器的 FileFilter.accept( java.IO.File) 方法返回 true 时,该路径名才满足过滤器,如果当前 File 对象不表示一个目录,或者发生 I/O 错误,则返回 null

递归打印多级目录

分析:多级目录的打印遍历之前,无从知道到底有多少级目录,所以可以使用递归实现

@Test
public void test3() {
     File dir = new File("d:/test");
     listSubFiles(dir);
}

public void listSubFiles(File dir) {
    if (dir != null && dir.isDirectory()) {
        File[] listFiles = dir.listFiles();
        if (listFiles != null) {
            for (File sub : listFiles) {
                listSubFiles(sub);//递归调用
            }
        }
    }
    System.out.println(dir);
}

递归打印某目录下(包括子目录)中所有满足条件的文件

列出”D:/test”下所有”.java”文件

    @Test
    public void test5() {
         File dir = new File("D:/test");
         listByFileFilter(dir);
    }

    public void listByFileFilter(File file) {
        if (file != null && file.isDirectory()) {
            File[] listFiles = file.listFiles(new FilenameFilter() {

                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(".java") || new File(dir,name).isDirectory();
                }
            });
            if (listFiles != null) {
                for (File sub : listFiles) {
                    if(sub.isFile()){
                        System.out.println(sub);
                    }
                    listByFileFilter(sub);
                }
            }
        }
    }

递归求目录总大小

    @Test
    public void test4() {
         File dir = new File("D:/test");
         long length = getLength(dir);
         System.out.println("大小:" + length);
    }

    public long getLength(File dir){
        if (dir != null && dir.isDirectory()) {
            File[] listFiles = dir.listFiles();
            if(listFiles!=null){
                long sum = 0;
                for (File sub : listFiles) {
                    sum += getLength(sub);
                }
                return sum;
            }
        }else if(dir != null && dir.isFile()){
            return dir.length();
        }
        return 0;
    }

代码二

public static int listSubFiles3(File file, int sum) {
    if (file.isDirectory()) {
        File[] files = file.listFiles((dir, name) -> new File(dir, name).isDirectory());
        for (File file1 : files) {
            sum += file1.length();
            sum += listSubFiles3(file1, sum);
        }
        return sum;
    }
    return 0;
}

递归删除非空目录

如果目录非空,连同目录下的文件和文件夹一起删除

    @Test
    public void test6() {
         File dir = new File("D:/test/javase");
         forceDeleteDir(dir);
    }
    public void forceDeleteDir(File dir) {
        if (dir != null && dir.isDirectory()) {
            File[] listFiles = dir.listFiles();
            if(listFiles!=null){
                for (File sub : listFiles) {
                    forceDeleteDir(sub);
                }
            }
        }
        dir.delete();
    }