files - Directories

陆飞龙
2023-12-01

The Files utility class contains most of the operations we'll need for directory and file manipulation. For some reason, however, they did not include a tool to delete directory trees, so here we create one.

// onjava/RmDir.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
package onjava;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class RmDir {
  public static void rmdir(Path dir) throws IOException {
    Files.walkFileTree(
        dir,
        new SimpleFileVisitor<Path>() {
          @Override
          public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
              throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
          }

          @Override
          public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
          }
        });
  }
}

This relies on Files.walkFileTree(); "walking the tree means looking at every subdirectory and file. The Vsitor design pattern provides a standard mechanism to visit every object in a collection, then we provide the action we want executed on each of those objects. This action is defined by how we implement the FileVisitor argument, which contains: 

  • preVisitDirectory(): Runs on a directory before entries in the directory are visited.
  • visitFile() : Runs on each file in the directory.
  • visitFileFailed() : Called for a file that cannot be visited.
  • postVisitDirectory() : Runs on a directory after entries in the directory—including all the subdirectories beneath it—are visited.

 

// files/Directories.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.

import java.nio.file.*;
import java.util.*;
import onjava.RmDir;

public class Directories {
  static Path test = Paths.get("test");
  static String sep = FileSystems.getDefault().getSeparator();
  static List<String> parts = Arrays.asList("foo", "bar", "baz", "bag");

  static Path makeVariant() {
    Collections.rotate(parts, 1);
    return Paths.get("test", String.join(sep, parts));
  }

  static void refreshTestDir() throws Exception {
    if (Files.exists(test)) {
      RmDir.rmdir(test);
    }
    if (!Files.exists(test)) {
      Files.createDirectory(test);
    }
  }

  public static void main(String[] args) throws Exception {
    refreshTestDir();
    Files.createFile(test.resolve("Hello.txt"));
    Path variant = makeVariant();
    // Throws exception (too many levels):
    try {
      Files.createDirectory(variant);
    } catch (Exception e) {
      System.out.println("Nope, that doesn't work.");
      e.printStackTrace();
    }
    populateTestDir();
    Path tempdir = Files.createTempDirectory(test, "DIR_");
    Files.createTempFile(tempdir, "pre", ".non");
    Files.newDirectoryStream(test).forEach(System.out::println);
    System.out.println("*********");
    Files.walk(test).forEach(System.out::println);
  }

  static void populateTestDir() throws Exception {
    for (int i = 0; i < parts.size(); i++) {
      Path variant = makeVariant();
      if (!Files.exists(variant)) {
        Files.createDirectories(variant);
        Files.copy(Paths.get("Directories.java"), variant.resolve("File.txt"));
        Files.createTempFile(variant, null, null);
      }
    }
  }
}
/* My Output:
Nope, that doesn't work.
java.nio.file.NoSuchFileException: test/bag/foo/bar/baz
        at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
        at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384)
        at java.nio.file.Files.createDirectory(Files.java:674)
        at Directories.main(Directories.java:35)
test/foo
test/baz
test/bar
test/bag
test/Hello.txt
test/DIR_5728185969641178576

*********
test
test/foo
test/foo/bar
test/foo/bar/baz
test/foo/bar/baz/bag
test/foo/bar/baz/bag/File.txt
test/foo/bar/baz/bag/1399888999375793947.tmp
test/baz
test/baz/bag
test/baz/bag/foo
test/baz/bag/foo/bar
test/baz/bag/foo/bar/File.txt
test/baz/bag/foo/bar/3512094328755573234.tmp
test/bar
test/bar/baz
test/bar/baz/bag
test/bar/baz/bag/foo
test/bar/baz/bag/foo/File.txt
test/bar/baz/bag/foo/8684150339761147431.tmp
test/bag
test/bag/foo
test/bag/foo/bar
test/bag/foo/bar/baz
test/bag/foo/bar/baz/File.txt
test/bag/foo/bar/baz/2931020737367562520.tmp
test/Hello.txt
test/DIR_5728185969641178576
test/DIR_5728185969641178576/pre861496518052453140.non
*/

rotate

public static void rotate(List<?> list,
                          int distance)

Rotates the elements in the specified list by the specified distance. After calling this method, the element at index i will be the element previously at index (i - distance) mod list.size(), for all values of i between 0and list.size()-1, inclusive. (This method has no effect on the size of the list.)

For example, suppose list comprises [t, a, n, k, s]. After invoking Collections.rotate(list, 1) (or Collections.rotate(list, -4)), list will comprise [s, t, a, n, k].

Note that this method can usefully be applied to sublists to move one or more elements within a list while preserving the order of the remaining elements. For example, the following idiom moves the element at index jforward to position k (which must be greater than or equal to j):

     Collections.rotate(list.subList(j, k+1), -1);
 

To make this concrete, suppose list comprises [a, b, c, d, e]. To move the element at index 1 (b) forward two positions, perform the following invocation:

     Collections.rotate(l.subList(1, 4), -1);
 

The resulting list is [a, c, d, b, e].

To move more than one element forward, increase the absolute value of the rotation distance. To move elements backward, use a positive shift distance.

If the specified list is small or implements the RandomAccess interface, this implementation exchanges the first element into the location it should go, and then repeatedly exchanges the displaced element into the location it should go until a displaced element is swapped into the first element. If necessary, the process is repeated on the second and successive elements, until the rotation is complete. If the specified list is large and doesn't implement the RandomAccess interface, this implementation breaks the list into two sublist views around index -distance mod size. Then the reverse(List) method is invoked on each sublist view, and finally it is invoked on the entire list. For a more complete description of both algorithms, see Section 2.3 of Jon Bentley's Programming Pearls (Addison-Wesley, 1986).

Parameters:

list - the list to be rotated.

distance - the distance to rotate the list. There are no constraints on this value; it may be zero, negative, or greater than list.size().

Throws:

UnsupportedOperationException - if the specified list or its list-iterator does not support the set operation.

Since:

1.4

 

copy

public static long copy(Path source,
                        OutputStream out)
                 throws IOException

Copies all bytes from a file to an output stream.

If an I/O error occurs reading from the file or writing to the output stream, then it may do so after some bytes have been read or written. Consequently the output stream may be in an inconsistent state. It is strongly recommended that the output stream be promptly closed if an I/O error occurs.

This method may block indefinitely writing to the output stream (or reading from the file). The behavior for the case that the output stream is asynchronously closed or the thread interrupted during the copy is highly output stream and file system provider specific and therefore not specified.

Note that if the given output stream is Flushable then its flush method may need to invoked after this method completes so as to flush any buffered output.

Parameters:

source - the path to the file

out - the output stream to write to

Returns:

the number of bytes read or written

Throws:

IOException - if an I/O error occurs when reading or writing

SecurityException - In the case of the default provider, and a security manager is installed, the checkRead method is invoked to check read access to the file.

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/onjava/RmDir.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/files/Directories.java

4. https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#rotate-java.util.List-int-

5. https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html

6. https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html

 类似资料: