Java NIO学习教程(八)

原文地址: link.

16.Java NIO Files

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实例,指向我们要检查的路径是否存在。其次,该示例使用Path实例作为第一个参数,调用Files.exists( )方法。

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

Files.createDirectory( )
Files.createDirectory( )方法从Path实例创建新目录。这是一个Java Files.createDirectory( )示例:

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

try {
    Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
    // the directory already exists.
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

第一行创建Path表示要创建的目录的实例。在try-catch块内部,Files.createDirectory()使用path作为参数调用方法。如果创建目录成功,Path则返回指向新创建的路径的实例。

如果该目录已存在,将引发java.nio.file.FileAlreadyExistsException。如果出现其他问题,IOException可能会被抛出。例如,如果所需的新目录的父目录不存在,则可能引发IOException。父目录是要在其中创建新目录的目录。因此,它表示新目录的父目录。

Files.copy( )
Files.copy( )方法将文件从一个路径复制到另一个路径。这是一个Java NIO 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) {
    //destination file already exists
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

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

如果目标文件已存在,则抛出java.nio.file.FileAlreadyExistsException。如果出现其他问题,将引发IOException。例如,如果要将文件复制到的目录不存在,则将引发IOException。

Overwriting Existing Files
可以强制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) {
    //destination file already exists
} catch (IOException e) {
    //something else went wrong
    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) {
    //moving file failed.
    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) {
    //deleting file failed
    e.printStackTrace();
}

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

Files.walkFileTree( )
Files.walkFileTree( )方法包含递归遍历目录树的功能。walkFileTree( )方法采用Path实例和FileVisitoras作为参数。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_SIBLINGS
    +SKIP_SUBTREE

通过返回这些值中的一个,被调用的方法可以决定文件遍历应该如何继续。

CONTINUE 表示文件遍历应该正常继续。

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

SKIP_SIBLINGS 表示文件遍历应该继续但不访问此文件或目录的任何兄弟。

SKIP_SUBTREE 表示文件遍历应该继续但不访问此目录中的条目。只有从previsitDirectory( )返回时,此值才具有函数。如果从任何其他方法返回,它将被解释为continue。

Searching For Files
这是一个walkFileTree( ),它扩展SimpleFileVisitor以查找名为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();
}

Deleting Directories Recursively
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();
}

Additional Methods in the Files Class
java.nio.file.files类包含许多其他有用的函数,例如用于创建符号链接、确定文件大小、设置文件权限等的函数。有关这些方法的详细信息,请查看java.nio.file.files类的javadoc。

【上篇】Java NIO学习教程(七)==>点击

【下篇】Java NIO学习教程(九)==>点击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值