NIO之Files方法介绍

538 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

一、概述

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表示文件遍历将继续,但不再访问此目录内的文件