Files.list 和 Files.walkFileTree 以及 Files.walk 和 maxdepth = 1 有什么区别?
What is the difference between Files.list and Files.walkFileTree and Files.walk with maxdepth = 1?
如果我只想对目录第一级的文件进行操作,
使用 Files.list(...)
或 Files.walkFileTree(...)
或 Files.walk(...)
之间有区别吗?
Files.walkFileTree(directory, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
// log exc
return FileVisitResult.CONTINUE;
}
});
对比
Files.list(directory)
.forEach(path -> {
try {
doSomething(path);
} catch (IOException exc) {
// log exc
}
});
对比
Files.walk(directory, 1)
.forEach(path -> {
try {
doSomething(path);
} catch (IOException exc) {
// log exc
}
});
所有这 3 个解决方案看起来都是正确的,但最好使用最简单和最易读的方法,所以 Files.list()
看起来很自然地解决了这个问题。
使用下面的代码作为测试,我掌握了问题的窍门。 walk*
和 list
之间的主要区别在于 list(dir)
在目录 dir
中给出了 文件流,而两者 walk*
方法 遍历其参数 的子树 ,包括 子树的根目录本身。
walk
和 walkFileTree
之间的区别在于它们为遍历树提供了不同的接口:walkFileTree
获取 FileVisitor
,walk
给出 Stream<Path>
.
public class FilesTest {
public static void main(String[] args) {
final String pwd = System.getProperty("user.dir");
System.out.println("Working Directory = " + pwd);
Path dir = Paths.get(pwd);
System.out.println("Files.walk");
try {
Files.walk(dir, 1).forEach(path -> FilesTest.doSomething("walk", path));
} catch (IOException e) {
logException("walk", e);
}
System.out.println("Files.walkFileTree");
try {
Files.walkFileTree(dir, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething("visitFile", file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
logException("visitFile", exc);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
logException("walkFileTree", e);
}
System.out.println("Files.list");
try {
Files.list(dir).forEach(path -> FilesTest.doSomething("dir", path));
} catch (IOException e) {
logException("dir", e);
}
}
private static void logException(String title, IOException e) {
System.err.println(title + "\terror: " + e);
}
private static void doSomething(String title, Path file) {
System.out.println(title + "\t: " + file);
}
}
Files.list
简单地委托给 Files.newDirectoryStream
并将底层 java.nio.file.DirectoryStream
公开为 java.util.stream.Stream
,因此它们的功能基本相同,除了 Files.newDirectoryStream
允许你传递一个可选的 DirectoryStream.Filter
.
Files.walkFileTree
还公开了 BasicFileAttributes
(例如 lastModifiedTime
、isRegularFile
和 size
)。如果您需要这些属性,从 Files.walkFileTree
获取它们可能更方便(也可能更有效),而不是单独查找它们。
如果我只想对目录第一级的文件进行操作,
使用 Files.list(...)
或 Files.walkFileTree(...)
或 Files.walk(...)
之间有区别吗?
Files.walkFileTree(directory, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
// log exc
return FileVisitResult.CONTINUE;
}
});
对比
Files.list(directory)
.forEach(path -> {
try {
doSomething(path);
} catch (IOException exc) {
// log exc
}
});
对比
Files.walk(directory, 1)
.forEach(path -> {
try {
doSomething(path);
} catch (IOException exc) {
// log exc
}
});
所有这 3 个解决方案看起来都是正确的,但最好使用最简单和最易读的方法,所以 Files.list()
看起来很自然地解决了这个问题。
使用下面的代码作为测试,我掌握了问题的窍门。 walk*
和 list
之间的主要区别在于 list(dir)
在目录 dir
中给出了 文件流,而两者 walk*
方法 遍历其参数 的子树 ,包括 子树的根目录本身。
walk
和 walkFileTree
之间的区别在于它们为遍历树提供了不同的接口:walkFileTree
获取 FileVisitor
,walk
给出 Stream<Path>
.
public class FilesTest {
public static void main(String[] args) {
final String pwd = System.getProperty("user.dir");
System.out.println("Working Directory = " + pwd);
Path dir = Paths.get(pwd);
System.out.println("Files.walk");
try {
Files.walk(dir, 1).forEach(path -> FilesTest.doSomething("walk", path));
} catch (IOException e) {
logException("walk", e);
}
System.out.println("Files.walkFileTree");
try {
Files.walkFileTree(dir, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething("visitFile", file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
logException("visitFile", exc);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
logException("walkFileTree", e);
}
System.out.println("Files.list");
try {
Files.list(dir).forEach(path -> FilesTest.doSomething("dir", path));
} catch (IOException e) {
logException("dir", e);
}
}
private static void logException(String title, IOException e) {
System.err.println(title + "\terror: " + e);
}
private static void doSomething(String title, Path file) {
System.out.println(title + "\t: " + file);
}
}
Files.list
简单地委托给 Files.newDirectoryStream
并将底层 java.nio.file.DirectoryStream
公开为 java.util.stream.Stream
,因此它们的功能基本相同,除了 Files.newDirectoryStream
允许你传递一个可选的 DirectoryStream.Filter
.
Files.walkFileTree
还公开了 BasicFileAttributes
(例如 lastModifiedTime
、isRegularFile
和 size
)。如果您需要这些属性,从 Files.walkFileTree
获取它们可能更方便(也可能更有效),而不是单独查找它们。