Java NIO系列教程(十六) Java NIO Files

原文地址  译者:章筱虎

java NIO Files类(java.nio.file.Files) 提供了操作文件的相关方法。本篇文章将会覆盖大多数常用的方法。Files类包含了很多方法,如果你需要的功能在文中没有提及,需要自己查阅JavaDoc文档确认,也许Files类提供了相应方法(译者注:但本文中没有涉及)

java.nio.file.Files类需要和java.nio.file.Path一起使用,在学习Files类前,你需要掌握Path类的相关用法。

Files.exists()

Files.exists()方法用来检查文件系统中是否存在某路径。

Path实例对应的路径可能在文件系统中并不存在。例如,如果打算新建一个文件夹,首先需要创建一个对应的Path实例,然后才能创建对应路径下的文件夹。

因为Path实例对应的路径在文件系统的存在性不确定,可以使用Files.exists()方法确认Path对应的路径是否存在 (也就是开发需要自己显式的去调用该方法确认)。

如下是Files.exists()的示例:

Path path = Paths.get("data/logging.properties");

boolean pathExists =
 Files.exists(path,
 new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});

示例中首先创建了一个Path。然后,通过调用Files.exists方法并将path作为第一个参数确认path对应的路径是否存在。
注意下Files.exist()方法的第二个参数。第二个参数数组是评判路径是否存在时使用的规则。示例中,数组包含LinkOption.NOFOLLOW_LINKS枚举类型,表示Files.exists不会跟进到路径中有连接的下层文件目录。表示path路径中如果有连接,Files.exists方法不会跟进到连接中去

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java NIO系列教程(十六) Java NIO Files

FavoriteLoading添加本文到我的收藏
  • Trackback 关闭
  • 评论 (3)
    • tyang513
    • 2020/10/14 11:42下午

    貌似没有翻译完?

    • darren_wang
    • 2020/11/24 9:44下午

    Files.walkFileTree()是个遍历文件系统的好工具,就是不能并发执行太可惜了。

    • wangjunlong
    • 2021/03/01 6:13下午

    补充翻译部分:

    Files.createDirectory()方法
    Files.createDirectory()基于Path实例创建目录,如下例:
    Path path = Paths.get(“data/subdir”);

    try {
    Path newDir = Files.createDirectory(path);
    } catch(FileAlreadyExistsException e){
    // 处理文件已存在的异常.
    } catch (IOException e) {
    //处理其它异常
    e.printStackTrace();
    }

    第一行创建代表对应目录的Path对象(实例,对象即实例,不再赘述),try-catch块中的Files.createDirectory(path)将第一行创建的path对象最为参数执行创建操作。如果创建成功,方法返回代表目录的path对象,
    如果要创建的目录已经存在,将抛出 FileAlreadyExistsException 异常。如果执行过程中有其他问题,如:要创建目录的父目录不存在,则会抛出 IOException 异常。

    Files.copy()方法
    Files.copy()方法将 源path对象指向的 文件按照目标path指定名称拷贝到目标path指向的目录下。如下例:
    Path sourcePath = Paths.get(“data/logging.properties”);
    Path destinationPath = Paths.get(“data/logging-copy.properties”);

    try {
    Files.copy(sourcePath, destinationPath);
    } catch(FileAlreadyExistsException e) {
    //destination file already exists
    } catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
    }

    例子中,首先创建 源path对象 和 目标path对象,然后将这两个path对象作为参数,调用Files.copy()方法。就会将源path指向的文件按照目标path指定名称拷贝到目标path指向目录下。
    如果目标path指向的文件已经存在,将抛出 java.nio.file.FileAlreadyExistsException 异常。如果执行过程中有其他问题,如:要拷贝的文件不存在,则会抛出 IOException 异常。

    覆盖已存在文件(Overwriting Existing Files)
    如果目标文件存在,调用Files.copy()方法时也可以将其覆盖。如下例:
    Path sourcePath = Paths.get(“data/logging.properties”);
    Path destinationPath = Paths.get(“data/logging-copy.properties”);

    try {
    Files.copy(sourcePath, destinationPath,
    StandardCopyOption.REPLACE_EXISTING);
    } catch(FileAlreadyExistsException e) {
    //destination file already exists
    } catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
    }

    注意:Files.copy() 的第三个参数 StandardCopyOption.REPLACE_EXISTING,它表示如果目标文件存在,则将其覆盖。

    Files.move()方法
    JAVA NIO Files 类中也有移动文件到目标路径的方法。移动文件与重命名文件一样,只是NIO 可以通过调用Files.move()完成移动和重命名两项操作。确实,java.io.File 类也可以通过其renameTo()方法完成上述功能,不过,现在你也可以使用NIO中的 java.nio.file.Files 类。
    Files.move()方法,如下例:
    Path sourcePath = Paths.get(“data/logging-copy.properties”);
    Path destinationPath = Paths.get(“data/subdir/logging-moved.properties”);

    try {
    Files.move(sourcePath, destinationPath,
    StandardCopyOption.REPLACE_EXISTING);
    } catch (IOException e) {
    //moving file failed.
    e.printStackTrace();
    }

    例子中,首先创建源path(sourcePath) 和目标path(destinationPath),源path指向要被移动的文件,目标path指向要移动到位置和名称。调用Files.move()方法后,文件将被移动。
    注意Files.move()中的第三个参数 StandardCopyOption.REPLACE_EXISTING,它表示移动过程中,如果目标文件存在,则覆盖它。这个选项为可选项。
    移动文件失败可能会触发IOException,比如:目标文件存在,而我们没有使用 StandardCopyOption.REPLACE_EXISTING 可选项。或者源文件不存在等。

    Files.walkFileTree()
    Files.walkFileTree()方法具备递归遍历目录树的功能。Files.walkFileTree()方法需要path 实例和 FileVisitor作为方法参数。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 {

    }

    必须自己实现FileVisitor接口,并将实现类的实例作为参数,传递到walkFileTree()方法中。FileVisitor实现类的全部方法会在目录遍历的过程中被调用。如果不想实现FileVisitor接口的全部方法,也可以直接继承 SimpleFileVisitor 类,这个类提供了 FileVisitor 接口全部方法的默认实现。
    接下来看看Files.walkFileTree()方法,示例如下:
    Files.walkFileTree(path, new FileVisitor() {
    @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;
    }
    });

    FileVisitor实现类的方法会在目录遍历的不同阶段被调用。
    访问每个目录前,都会先调用 preVisitDirectory()方法 ,访问目录之后会调用postVisitDirectory()方法。
    文件遍历期间访问每个文件,都会调用visitFile()方法。这个方法只在遍历文件时调用,遍历目录时不调用。
    遍历文件失败时,会调用visitFileFailed() 方法。比如,程序没有正确的权限或者其它问题。
    FileVisitor实现类方法都会返回 FileVisitResult 枚举实例。FileVisitResult 枚举包含以下四项:
    CONTINUE
    TERMINATE
    SKIP_SIBLINGS
    SKIP_SUBTREE
    根据返回的不同枚举值,Files.walkFileTree()会采取不同的方式执行后续遍历。
    CONTINUE:表示文件遍历将按默认方式继续。
    TERMINATE:表示终止遍历。
    SKIP_SIBLINGS:表示跳过当前同级的目录和文件,继续遍历。
    SKIP_SUBTREE:表示跳过当前目录的子节点,继续遍历。这个枚举值只在作为preVisitDirectory()返回值时生效,如果作为其他方法的返回值,则会被视为CONTINUE。

    查找文件(Searching For Files)
    下面是一个继承自 SimpleFileVisitor 类,用于查找 README.txt 文件的例子:
    Path rootPath = Paths.get(“data”);
    String fileToFind = File.separator + “README.txt”;

    try {
    Files.walkFileTree(rootPath, new SimpleFileVisitor() {

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    String fileString = file.toAbsolutePath().toString();
    //System.out.println(“pathString = ” + fileString);

    if(fileString.endsWith(fileToFind)){
    System.out.println(“file found at path: ” + file.toAbsolutePath());
    return FileVisitResult.TERMINATE;
    }
    return FileVisitResult.CONTINUE;
    }
    });
    } catch(IOException e){
    e.printStackTrace();
    }

    递归删除目录(Deleting Directories Recursively)
    Files.walkFileTree()方法也可以用于删除目录(包括目录包含的文件及子目录)。Files.delete()方法只能删除文件和空目录,但可以结合Files.walkFileTree(),完成目录的递归删除。具体实现为:通过FileVisitor实现类的visitFile()方法,逐个删除遍历目录中的文件,删除完目录包含的文件后,通过FileVisitor实现类的postVisitDirectory()方法删除目录本身。递归目录删除如下例:
    Path rootPath = Paths.get(“data/to-delete”);

    try {
    Files.walkFileTree(rootPath, new SimpleFileVisitor() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    System.out.println(“delete file: ” + file.toString());
    Files.delete(file);
    return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
    Files.delete(dir);
    System.out.println(“delete dir: ” + dir.toString());
    return FileVisitResult.CONTINUE;
    }
    });
    } catch(IOException e){
    e.printStackTrace();
    }

    Files 类中的其他方法
    java.nio,file.Files 类包含了很多有用的方法,如创建符号链接、确定文件大小、设置文件权限等。java.nio,file.Files详情可查阅javaDoc 。

return top