问题
I know of the Apache Commons IO library for file directory processing in Java. However, List all files from a directory recursively with Java talks about native support in Java 7.
Does anyone have experience on how to recursively list/read files in a directory using Java 7?
回答1:
There's a tutorial on it. Basically you implement a Visitor which can then be called as directories are entered, exited, and files are encountered. There is support for determining if files are symbolic links, and options to follow the symbolic link (if you care to do so). A quick read on what Java Path
s are might be useful, and the entire documentation starts here.
import static java.nio.file.FileVisitResult.*;
public static class PrintFiles
extends SimpleFileVisitor<Path> {
// Print information about
// each type of file.
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr) {
if (attr.isSymbolicLink()) {
System.out.format("Symbolic link: %s ", file);
} else if (attr.isRegularFile()) {
System.out.format("Regular file: %s ", file);
} else {
System.out.format("Other: %s ", file);
}
System.out.println("(" + attr.size() + "bytes)");
return CONTINUE;
}
// Print each directory visited.
@Override
public FileVisitResult postVisitDirectory(Path dir,
IOException exc) {
System.out.format("Directory: %s%n", dir);
return CONTINUE;
}
// If there is some error accessing
// the file, let the user know.
// If you don't override this method
// and an error occurs, an IOException
// is thrown.
@Override
public FileVisitResult visitFileFailed(Path file,
IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
A second example (from the Java implementation of find
) that illustrates file walking could be easily modified to "match" all files.
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import static java.nio.file.FileVisitResult.*;
import static java.nio.file.FileVisitOption.*;
import java.util.*;
/**
* Sample code that finds files that
* match the specified glob pattern.
* For more information on what
* constitutes a glob pattern, see
* http://docs.oracle.com/javase/javatutorials/tutorial/essential/io/fileOps.html#glob
*
* The file or directories that match
* the pattern are printed to
* standard out. The number of
* matches is also printed.
*
* When executing this application,
* you must put the glob pattern
* in quotes, so the shell will not
* expand any wild cards:
* java Find . -name "*.java"
*/
public class Find {
/**
* A {@code FileVisitor} that finds
* all files that match the
* specified pattern.
*/
public static class Finder
extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern) {
matcher =
FileSystems.getDefault()
.getPathMatcher("glob:" + pattern);
}
// Compares the glob pattern against
// the file or directory name.
void find(Path file) {
Path name = file.getFileName();
if (name != null && matcher.matches(name)) {
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done() {
System.out.println("Matched: "
+ numMatches);
}
// Invoke the pattern matching
// method on each file.
@Override
public FileVisitResult
visitFile(Path file,
BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
@Override
public FileVisitResult
preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
@Override
public FileVisitResult
visitFileFailed(Path file,
IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
static void usage() {
System.err.println("java Find <path>" +
" -name \"<glob_pattern>\"");
System.exit(-1);
}
public static void main(String[] args)
throws IOException {
if (args.length < 3
|| !args[1].equals("-name"))
usage();
Path startingDir = Paths.get(args[0]);
String pattern = args[2];
Finder finder = new Finder(pattern);
Files.walkFileTree(startingDir, finder);
finder.done();
}
}
On my system (Linux / Fedora), it worked well; however, I was only testing it for functionality, and playing around with it. I didn't stress test it for performance or any other meaningful measurement (beyond "it works").
回答2:
Use Files.walkFileTree.
(Have no experience using it, but I just found it in the docs and it looks straightforward to use.)
来源:https://stackoverflow.com/questions/10523585/how-to-read-files-recursively-in-java-7