美文网首页java技术基础java nioJava学习笔记
Java NIO 教程(十五) Java NIO Files

Java NIO 教程(十五) Java NIO Files

作者: 步积 | 来源:发表于2017-06-19 18:39 被阅读2187次

    原文地址

    目录

    Java NIO Files类(java.nio.file.Files)提供了几种操作文件系统中的文件的方法。这个Java NIO Files教程将介绍最常用的这些方法。Files类包含许多方法,所以如果您需要一个在这里没有描述的方法,那么请检查JavaDoc。Files类可能还会有一个方法来实现它。

    java.nio.file.Files类与java.nio.file.Path实例一起工作,因此在处理Files类之前,您需要了解Path类。

    Files.exists()

    Files.exists()方法检查给定的Path在文件系统中是否存在。

    可以创建在文件系统中不存在的Path实例。例如,如果您计划创建一个新目录,您首先要创建相应的Path实例,然后创建目录。

    由于Path实例可能指向,也可能没有指向文件系统中存在的路径,你可以使用Files.exists()方法来确定它们是否存在(如果需要检查的话)。

    这里是一个Java Files.exists()的例子:

    Path path = Paths.get("data/logging.properties");
    
    boolean pathExists =
            Files.exists(path,
                new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});
    

    这个例子首先创建一个Path实例指向一个路径,我们想要检查这个路径是否存在。然后,这个例子调用Files.exists()方法,然后将Path实例作为第一个参数。

    注意Files.exists()方法的第二个参数。这个参数是一个选项数组,它影响Files.exists()如何确定路径是否存在。在上面的例子中的数组包含LinkOption.NOFOLLOW_LINKS,这意味着Files.exists()方法不应该在文件系统中跟踪符号链接,以确定文件是否存在。

    Files.createDirectory()

    Files.createDirectory()方法,用于根据Path实例创建一个新目录,下面是一个Files.createDirectory()例子:

    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实例,该实例指向新创建的路径。

    如果该目录已经存在,则是抛出一个java.nio.file.FileAlreadyExistsException。如果出现其他错误,可能会抛出IOException。例如,如果想要的新目录的父目录不存在,则可能会抛出IOException。父目录是您想要创建新目录的目录。因此,它表示新目录的父目录。

    Files.copy()

    Files.copy()方法从一个路径拷贝一个文件到另外一个目录,这里是一个Java Files.copy()例子:

    Path sourcePath      = Paths.get("data/logging.properties");
    Path destinationPath = Paths.get("data/logging-copy.properties");
    
    try {
        Files.copy(sourcePath, destinationPath);
    } catch(FileAlreadyExistsException e) {
        // 目录已经存在
    } catch (IOException e) {
        // 其他发生的异常
        e.printStackTrace();
    }
    

    首先,该示例创建一个源和目标Path实例。然后,这个例子调用Files.copy(),将两个Path实例作为参数传递。这可以让源路径引用的文件被复制到目标路径引用的文件中。

    如果目标文件已经存在,则抛出一个java.nio.file.FileAlreadyExistsException异常。如果有其他错误,则会抛出一个IOException。例如,如果将该文件复制到不存在的目录,则会抛出IOException

    重写已存在的文件

    可以强制Files.copy()覆盖现有的文件。这里有一个示例,演示如何使用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) {
        // 目标文件已存在
    } catch (IOException e) {
        // 其他发生的异常
        e.printStackTrace();
    }
    

    请注意Files.copy()方法的第三个参数。如果目标文件已经存在,这个参数指示copy()方法覆盖现有的文件。

    Files.move()

    Java NIO Files还包含一个函数,用于将文件从一个路径移动到另一个路径。移动文件与重命名相同,但是移动文件既可以移动到不同的目录,也可以在相同的操作中更改它的名称。是的,java.io.File类也可以使用它的renameTo()方法来完成这个操作,但是现在已经在java.nio.file.Files中有了文件移动功能。

    这里有一个Java 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) {
        //移动文件失败
        e.printStackTrace();
    }
    

    首先创建源路径和目标路径。源路径指向要移动的文件,而目标路径指向文件应该移动到的位置。然后调用Files.move()方法。这会导致文件被移动。

    请注意传递给Files.move()的第三个参数。这个参数告诉Files.move()方法来覆盖目标路径上的任何现有文件。这个参数实际上是可选的。

    如果移动文件失败,Files.move()方法可能抛出一个IOException。例如,如果一个文件已经存在于目标路径中,并且您已经排除了StandardCopyOption.REPLACE_EXISTING选项,或者被移动的文件不存在等等。

    Files.delete()

    Files.delete()方法可以删除一个文件或者目录。下面是一个Java Files.delete()例子:

    Path path = Paths.get("data/subdir/logging-moved.properties");
    
    try {
        Files.delete(path);
    } catch (IOException e) {
        // 删除文件失败
        e.printStackTrace();
    }
    

    首先,创建指向要删除的文件的Path。然后调用Files.delete()方法。如果Files.delete()由于某种原因不能删除文件(例如,文件或目录不存在),会抛出一个IOException

    Files.walkFileTree()

    Files.walkFileTree()方法包含递归遍历目录树的功能。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实现的每个方法都将被调用。如果不需要实现所有这些方法,那么可以扩展SimpleFileVisitor类,它包含FileVisitor接口中所有方法的默认实现。

    这里是一个walkFileTree()的例子:

    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;
      }
    });
    

    FileVisitor实现中的每个方法在遍历过程中的不同时间都被调用:

    在访问任何目录之前调用preVisitDirectory()方法。在访问一个目录之后调用postVisitDirectory()方法。

    调用visitFile()在文件遍历过程中访问的每一个文件。它不会访问目录-只会访问文件。在访问文件失败时调用visitFileFailed()方法。例如,如果您没有正确的权限,或者其他什么地方出错了。

    这四个方法中的每个都返回一个FileVisitResult枚举实例。FileVisitResult枚举包含以下四个选项:

    • CONTINUE 继续
    • TERMINATE 终止
    • SKIP_SIBLING 跳过同级
    • SKIP_SUBTREE 跳过子级

    通过返回其中一个值,调用方法可以决定如何继续执行文件。

    CONTINUE继续意味着文件的执行应该像正常一样继续。

    TERMINATE终止意味着文件遍历现在应该终止。

    SKIP_SIBLINGS跳过同级意味着文件遍历应该继续,但不需要访问该文件或目录的任何同级。

    SKIP_SUBTREE跳过子级意味着文件遍历应该继续,但是不需要访问这个目录中的子目录。这个值只有从preVisitDirectory()返回时才是一个函数。如果从任何其他方法返回,它将被解释为一个CONTINUE继续。

    文件搜索

    这里是一个用于扩展SimpleFileVisitorwalkFileTree(),以查找一个名为README.txt的文件:

    Path rootPath = Paths.get("data");
    String fileToFind = File.separator + "README.txt";
    
    try {
      Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
        
        @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();
    }
    

    递归删除目录

    Files.walkFileTree()也可以用来删除包含所有文件和子目录的目录。Files.delete()方法只会删除一个目录,如果它是空的。通过遍历所有目录并删除每个目录中的所有文件(在visitFile())中,然后删除目录本身(在postVisitDirectory()中),您可以删除包含所有子目录和文件的目录。下面是一个递归目录删除示例:

    Path rootPath = Paths.get("data/to-delete");
    
    try {
      Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
        @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();
    }
    

    文件类中的其他方法

    java.nio.file.Files类包含许多其他有用的函数,比如用于创建符号链接的函数、确定文件大小、设置文件权限等等。有关这些方法的更多信息,请查看java.nio.file.Files类的JavaDoc。

    相关文章

      网友评论

        本文标题:Java NIO 教程(十五) Java NIO Files

        本文链接:https://www.haomeiwen.com/subject/kmknqxtx.html