2023-09-23
原文作者:李林超 原文地址: https://www.lilinchao.com/archives/2094.html

[TOC]

一、概述

Files是Java1.7 在nio中新增的专门用于处理文件和目录的工具类。FilesPath配合可以很方便的完成对文件/目录的创建、读取、修改、删除等操作。

二、常用方法介绍

2.1 Files.exits()

boolean exists(Path path, LinkOption... options)

描述 :方法检查一个路径是否存在于当前的文件系统中。

参数

  • Path :传入的文件路径。 必须
  • LinkOption:exits()方法的选项数组。如LinkOption.NOFOLLOW_LINKS代表不允许跟随文件系统中的符号链接来确定路径是否存在。 非必须
    Path path = Paths.get("D:\\path_test\\demo");
    
    boolean exists = Files.exists(path);
    System.out.println(exists);

2.2 Files.createDirectory()

createDirectory(Path dir, FileAttribute<?>... attrs)

描述 :此方法使用给定的路径创建目录,如果创建目录成功,它将返回创建的目录的路径。

参数

  • Path :需要创建的文件路径。 必须
  • FileAttribute:是在创建不存在的目录时自动设置的可选参数,它返回创建的目录的路径。 非必须

注意

  • 如果目录已经存在,那么它会抛出 nio.file.FileAlreadyExistsException。
  • 不能一次创建多级目录,否则会抛异常 NoSuchFileException
    Path path = Paths.get("D:\\path_test\\demo2");
    Files.createDirectories(path);

2.3 Files.createDirectories()

createDirectories(Path dir, FileAttribute<?>... attrs)

描述 :此方法通过首先创建所有不存在的父目录来使用给定路径创建目录。如果由于目录已存在而无法创建该目录,则此方法不会引发异常。

该方法用来创建多级目录。

    Path path = Paths.get("D:\\path_test\\demo3\\a\\b");
    Files.createDirectories(path);

2.4 Files.copy()

long copy(InputStream in, Path target, CopyOption... options)

描述 :此方法将指定输入流中的所有字节复制到指定目标文件,并返回读取或写入的字节数作为长值。

  • 将InputStream中的数据复制到目标文件
    InputStream inputStream = new FileInputStream("D:\\path_test\\demo\\first_input.txt");
    Path targetPath = Paths.get("D:\\path_test\\demo3\\first_copy2.txt");
    
    long size = Files.copy(inputStream, targetPath, StandardCopyOption.REPLACE_EXISTING);
    System.out.println(size);

注意

  • 默认情况,如果目标文件已经存在或是一个符号链接,则复制失败;
  • 指定了REPLACE_EXISTING的情况,如果目标文件已经存在,那么只要它不是一个非空目录(例如它是一个空目录,或者是一个符号链接),它就会被替换。截止到JDK1.8,options只支持REPLACE_EXISTING

long copy(Path source, OutputStream out)

描述 :此方法将指定源文件中的所有字节复制到给定的输出流,并返回读取或写入的字节数作为长值。

  • 将本地文件中的内容复制到OutputStream
    Path path = Paths.get("D:\\path_test\\demo\\first_copy.txt");
    OutputStream outputStream = new FileOutputStream("D:\\path_test\\demo\\first_output.txt");
    
    long size = Files.copy(path, outputStream);
    System.out.println(size);

注意

  • 当发生异常的时候,由于输出了可能已经获取到了一部分内容,所以输出流此时的内容可能很奇怪,应该直接关闭。
  • 如果输出流是Flushable的实现类的实例,在执行完方法以后应该调用flush方法以刷新缓存。

Path copy(Path source, Path target, CopyOption... options)

描述 :此方法将给定的源文件复制到指定的目标文件,并返回目标文件的路径。

  • 将文件first_copy.txt复制到文件first_copy2.txt
    Path path = Paths.get("D:\\path_test\\demo3\\first_copy.txt");
    Path targetPath = Paths.get("D:\\path_test\\demo3\\first_copy2.txt");
    
    Path copy = Files.copy(path, targetPath);
    System.out.println(copy);

注意

  • 在默认情况下,如果目标文件已经存在,或者是一个符号链接,那么复制失败;

options参数

参数 说明
REPLACE_EXISTING 如果目标文件已经存在,那么只要它不是一个非空目录,它就会被替换。
COPY_ATTRIBUTES 把source的文件属性复制给target,被复制的属性取决于平台和文件系统,但是至少在source和target都支持的情况下,会复制最新修改时间。
NOFOLLOW_LINKS 直接复制符号链接自身,而不是符号链接指向的目的地。可被复制的属性也会被复制,也就是说NOFOLLOW_LINKS的情况下配置COPY_ATTRIBUTES是没有意义的。

2.5 Files.move()

move(Path source, Path target, CopyOption... options)

描述 :此方法将源文件移动或重命名为目标文件,并返回目标文件的路径。

    Path sourcePath = Paths.get("D:\\path_test\\demo\\first_copy.txt");
    Path targetPath = Paths.get("D:\\path_test\\demo3\\first_copy2.txt");
    
    Path move = Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
    System.out.println(move);

options参数

参数 说明
REPLACE_EXISTING 如果目标文件存在,则如果它不是非空目录,则替换它。
ATOMIC_MOVE 表示移动文件作为原子文件系统操作执行,所有其他选项都被忽略。

注意

  • 如果目标文件存在但由于未指定 REPLACE_EXISTING 选项而无法替换,则此方法将引发 FileAleadyExistsException
  • 如果指定了 REPlACE_EXISTING 选项,则此方法将引发 DirectoryNotEmptyException 但无法替换该文件,因为它是一个非空目录。

2.6 Files.delete()

void delete(Path path)

描述 :删除一个文件或文件夹。

    Path path = Paths.get("D:\\path_test\\demo");
    
    //如果path指定到一个目录,并且目标不为空时会抛出异常
    Files.delete(path);

如果目标存在,并且是文件或者空的文件夹,就删除文件;如果目标不存在,或者目标是非空的文件夹,就会抛出异常。

2.7 Files.walkFileTree()

描述Files.walkFileTree()方法可以递归遍历目录树。它使用一个Path和一个FileVisitor作为参数。

首先先展示一下FileVisitor接口

    public interface FileVisitor {
    
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException;
    
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException;
    
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException;
    
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException;
    }

Files.walkFileTree()方法需要一个FileVisitor的实现类作为参数,实现FileVisitor接口就需要实现上述方法。

如果不想做特殊实现或者只想实现一部分,可以继承SimpleFileVisitor类,它其中有对FileVisitor的方法的默认实现。

示例

    Files.walkFileTree(path, new FileVisitor<Path>() {
      @Override
      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        System.out.println("pre visit dir:" + dir);
        return FileVisitResult.CONTINUE;
      }
    
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        System.out.println("visit file: " + file);
        return FileVisitResult.CONTINUE;
      }
    
      @Override
      public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
        System.out.println("visit file failed: " + file);
        return FileVisitResult.CONTINUE;
      }
    
      @Override
      public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
        System.out.println("post visit directory: " + dir);
        return FileVisitResult.CONTINUE;
      }
    });

这些方法在遍历的不同时间被调用

  • preVisitDirectory()方法在访问任何目录前被调用。
  • postVisitDirectory()方法在访问任何目录后被调用。
  • visitFile()方法在访问任何文件时被调用。
  • visitFileFailed()在访问任何文件失败时被调用。(比如没权限)

每个方法返回一个FileVisitResult枚举,这些返回指决定了遍历如何进行。

包括

参数 说明
CONTINUE 表示遍历将继续正常进行
TERMINATE 表示文件遍历将终止
SKIP_SIBLINGS 表示文件遍历将继续,但不在访问此文件/目录的同级文件/目录
SKIP_SUBTREE 表示文件遍历将继续,但不再访问此目录内的文件
阅读全文