Reprint the use of the Files class in Java NIO

The Files class (java.nio.file.Files) in Java NIO provides a variety of methods for manipulating files in the file system.

Files.exists()

The Files.exits() method is used to check whether the given Path exists in the file system. It is possible to create a Payh in the file system that does not exist otherwise. For example, if you want to create a new directory, then create the corresponding Path instance, and then create the directory.

Since the Path instance may point to a non-existing path in the file system, it needs to be confirmed with Files.exists().

Here is an example using Files.exists():

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

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

In this example, we first create a Path object, and then use Files.exists() to check if the path actually exists.

Note the second parameter of Files.exists(). It is an array, and this parameter directly affects how Files.exists() determines whether a path exists. In this case, this array contains LinkOptions.NOFOLLOW_LINKS, which means that no symbolic link files are included in the detection.

Files.createDirectory()

Files.createDirectory() will create the path represented by Path, the following is an example:

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

The first line creates a Path instance, representing the directory that needs to be created. Then use try-catch to capture the call to Files.createDirectory(). If the creation is successful, the return value is the newly created path.

If the directory already exists, a java.nio.file.FileAlreadyExistException will be thrown. If something else goes wrong, an IOException is thrown. For example, if the parent directory of the directory to be created does not exist, an IOException will be thrown. The parent directory refers to the location where the directory you want to create is located. That is, the parent directory above the newly created directory.

Files.copy()

The Files.copy() method copies a file from one location to another. E.g:

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

In this example, Path instances of the original file and the target file are first created. Then pass them as parameters to Files.copy(), and the file will be copied.

If the target file already exists, a java.nio.file.FileAlreadyExistsException will be thrown. Similarly, if an error occurs in the middle of spit, an IOException will also be thrown.

Overwriting Existing Files

The copy operation can force overwriting an existing target file. Here's a concrete example:

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

Note the third parameter of the copy method, this parameter determines whether the file can be overwritten.

Files.move()

The Files class of Java NIO also contains an interface for moving files. Moving a file is the same as renaming, but also changes the directory location of the file. The renameTo() method in the java.io.File class has the same function.

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

First create the source path and the target path, the original path refers to the initial path of the file to be moved, and the target path refers to the location to be moved.

The third argument to move here also allows us to overwrite existing files.

Files.delete()

The Files.delete() method deletes a file or directory:

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

try {
    Files.delete(path);
} catch (IOException e) {
    //deleting file failed
    e.printStackTrace();
}

First create the path object of the file that needs to be deleted. Then you can call delete.

Files.walkFileTree()

The Files.walkFileTree() method has the function of recursively traversing directories. walkFileTree accepts a Path and FileVisitor as parameters. The Path object is the directory to be traversed, and FileVistor will be called in each traversal.

Let's take a look at the definition of the FileVisitor interface:

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 needs to be implemented by the caller, and then each method passed to walkFileTree().FileVisitor as a parameter will be called multiple times during the traversal process. If you don't need to deal with each method, you can inherit his default implementation class SimpleFileVisitor, which makes all interfaces empty.

Let's see an example of 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;
  }
});

The methods of FileVisitor are called at different times: preVisitDirectory() is called before accessing the directory. postVisitDirectory() is called after a visit.

visitFile() will be called every time the file is visited throughout the traversal. He is not for directories, but for files. The visitFileFailed() call is made when file access fails. For example, when the appropriate permissions are missing or other errors.

The above four methods all return a FileVisitResult enumeration object. Specific optional enumeration items include:

  • CONTINUE
  • TERMINATE
  • SKIP_SIBLINGS
  • SKIP_SUBTREE

Returning this enumeration value allows the caller to decide whether the file traversal needs to continue. CONTINE means that file traversal continues as normal.

TERMINATE indicates that file access needs to be terminated.

SKIP_SIBLINGS indicates that file access continues, but access to other sibling files or directories is not required.

SKIP_SUBTREE means to continue to access, but do not need to access the subdirectories under this directory. This enumeration value is only valid when returned in preVisitDirectory(). If it is returned in other methods, it will be understood as CONTINE.

Searching For Files

Let's look at an example where we use walkFileTree() to find a README.txt file:

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 Directions Recursively

Files.walkFileTree() can also be used to delete a directory and all files and subdirectories inside it. Files.delete() is only used to delete an empty directory. We do this by traversing the directory, then all files in the visitFile() interface three times, and finally deleting the directory itself in 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();
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324727832&siteId=291194637