使用 Java 8 个流仅列出特定深度的文件夹
List only folders of certain depth using Java 8 streams
考虑到 Java 中有 "new" 8 我可以使用 Files.walk
遍历文件夹。如果使用此方法或 depth=2,我如何才能只获取给定目录的子文件夹?
我目前有这个工作示例,遗憾的是它也将根路径打印为所有 "subfolders"。
Files.walk(Paths.get("/path/to/stuff/"))
.forEach(f -> {
if (Files.isDirectory(f)) {
System.out.println(f.getName());
}
});
因此我恢复为以下approach。它将文件夹存储在内存中,之后需要处理存储的列表,我会避免并改用 lambdas。
File[] directories = new File("/your/path/").listFiles(File::isDirectory);
仅列出给定目录的子目录:
Path dir = Paths.get("/path/to/stuff/");
Files.walk(dir, 1)
.filter(p -> Files.isDirectory(p) && ! p.equals(dir))
.forEach(p -> System.out.println(p.getFileName()));
你也可以试试这个:
private File getSubdirectory(File file){
try {
return new File(file.getAbsolutePath().substring(file.getParent().length()));
}catch (Exception ex){
}
return null;
}
收集文件:
File[] directories = Arrays.stream(new File("/path/to/stuff")
.listFiles(File::isDirectory)).map(Main::getSubdirectory)
.toArray(File[]::new);
同意Andreas的回答,你也可以用Files.list代替Files.walk
Files.list(Paths.get("/path/to/stuff/"))
.filter(p -> Files.isDirectory(p) && ! p.equals(dir))
.forEach(p -> System.out.println(p.getFileName()));
您可以使用 Files#walk
方法的第二个重载来显式设置最大深度。跳过流的第一个元素以忽略根路径,然后您可以仅过滤目录以最终打印每个目录。
final Path root = Paths.get("<your root path here>");
final int maxDepth = <your max depth here>;
Files.walk(root, maxDepth)
.skip(1)
.filter(Files::isDirectory)
.map(Path::getFileName)
.forEach(System.out::println);
这是一个适用于任意 minDepth
和 maxDepth
也大于 1 的解决方案。假设 minDepth >= 0
和 minDepth <= maxDepth
:
final int minDepth = 2;
final int maxDepth = 3;
final Path rootPath = Paths.get("/path/to/stuff/");
final int rootPathDepth = rootPath.getNameCount();
Files.walk(rootPath, maxDepth)
.filter(e -> e.toFile().isDirectory())
.filter(e -> e.getNameCount() - rootPathDepth >= minDepth)
.forEach(System.out::println);
要完成您最初在列表问题中提出的问题 "...仅文件夹 某些 深度...",只需确保 minDepth == maxDepth
.
public List<String> listFilesInDirectory(String dir, int depth) throws IOException {
try (Stream<Path> stream = Files.walk(Paths.get(dir), depth)) {
return stream
.filter(file -> !Files.isDirectory(file))
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toList());
}
}
考虑到 Java 中有 "new" Files.walk
遍历文件夹。如果使用此方法或 depth=2,我如何才能只获取给定目录的子文件夹?
我目前有这个工作示例,遗憾的是它也将根路径打印为所有 "subfolders"。
Files.walk(Paths.get("/path/to/stuff/"))
.forEach(f -> {
if (Files.isDirectory(f)) {
System.out.println(f.getName());
}
});
因此我恢复为以下approach。它将文件夹存储在内存中,之后需要处理存储的列表,我会避免并改用 lambdas。
File[] directories = new File("/your/path/").listFiles(File::isDirectory);
仅列出给定目录的子目录:
Path dir = Paths.get("/path/to/stuff/");
Files.walk(dir, 1)
.filter(p -> Files.isDirectory(p) && ! p.equals(dir))
.forEach(p -> System.out.println(p.getFileName()));
你也可以试试这个:
private File getSubdirectory(File file){
try {
return new File(file.getAbsolutePath().substring(file.getParent().length()));
}catch (Exception ex){
}
return null;
}
收集文件:
File[] directories = Arrays.stream(new File("/path/to/stuff")
.listFiles(File::isDirectory)).map(Main::getSubdirectory)
.toArray(File[]::new);
同意Andreas的回答,你也可以用Files.list代替Files.walk
Files.list(Paths.get("/path/to/stuff/"))
.filter(p -> Files.isDirectory(p) && ! p.equals(dir))
.forEach(p -> System.out.println(p.getFileName()));
您可以使用 Files#walk
方法的第二个重载来显式设置最大深度。跳过流的第一个元素以忽略根路径,然后您可以仅过滤目录以最终打印每个目录。
final Path root = Paths.get("<your root path here>");
final int maxDepth = <your max depth here>;
Files.walk(root, maxDepth)
.skip(1)
.filter(Files::isDirectory)
.map(Path::getFileName)
.forEach(System.out::println);
这是一个适用于任意 minDepth
和 maxDepth
也大于 1 的解决方案。假设 minDepth >= 0
和 minDepth <= maxDepth
:
final int minDepth = 2;
final int maxDepth = 3;
final Path rootPath = Paths.get("/path/to/stuff/");
final int rootPathDepth = rootPath.getNameCount();
Files.walk(rootPath, maxDepth)
.filter(e -> e.toFile().isDirectory())
.filter(e -> e.getNameCount() - rootPathDepth >= minDepth)
.forEach(System.out::println);
要完成您最初在列表问题中提出的问题 "...仅文件夹 某些 深度...",只需确保 minDepth == maxDepth
.
public List<String> listFilesInDirectory(String dir, int depth) throws IOException {
try (Stream<Path> stream = Files.walk(Paths.get(dir), depth)) {
return stream
.filter(file -> !Files.isDirectory(file))
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toList());
}
}