【问题标题】:How to 'walk' multiple directories, with multiple file extensions, in java?java - 如何在java中“遍历”具有多个文件扩展名的多个目录?
【发布时间】:2020-06-28 01:39:23
【问题描述】:

这是我的实际代码,完美运行:
String sHomeDir 是我唯一开始扫描的文件夹
String sExt 是唯一要搜索的扩展名

try (Stream<Path> walk = Files.walk(Paths.get(sHomeDir)))
{
    List<String> result = walk.map(x -> x.toString())
        .filter(f -> f.endsWith(sExt)).collect(Collectors.toList());
    ...
} catch (IOException e) {
   e.printStackTrace();
}

是否可以重写,以便使用:
- 要扫描的多个文件夹(带有子树)
- 多个文件扩展名搜索

【问题讨论】:

  • 是的。从弄清楚如何过滤多个扩展程序开始。

标签: java file search subtree


【解决方案1】:

我想使用与“File.list()”方法一起使用的 FilenameFilter。我找到了一个样本here

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;

/**
 * 
 * @see: https://stackoverflow.com/questions/5751335/using-file-listfiles-with-filenameextensionfilter
 * 
 * <h3>setup filter like:</h3>
 * private static final ExtensionsFilenameFilter IMAGE_FILTER = <br/>
      new ExtensionsFilenameFilter(".png", ".jpg", ".bmp"); 
 * 
 */
public class ExtensionsFilenameFilter implements FilenameFilter {
    
    private char[][] extensions;

    public ExtensionsFilenameFilter(String... extensions)
    {
        int length = extensions.length;
        this.extensions = new char[length][];
        for (String s : extensions)
        {
            this.extensions[--length] = s.toCharArray();
        }
    }

    @Override
    public boolean accept(File dir, String name) {
        char[] path = name.toCharArray();
        for (char[] extension : extensions)
        {
            if (extension.length > path.length)
            {
                continue;
            }
            int pStart = path.length - 1;
            int eStart = extension.length - 1;
            boolean success = true;
            for (int i = 0; i <= eStart; i++)
            {
                if ((path[pStart - i] | 0x20) != (extension[eStart - i] | 0x20))
                {
                    success = false;
                    break;
                }
            }
            if (success)
                return true;
        }
        return false;
    }

}

然后我遍历根路径下的所有路径:

public void walkList(String path) throws IOException {
    List<String> imagefiles = new ArrayList<>();
    Files.walk(Paths.get(path))
    .filter(Files::isDirectory)
    .map(walkPath -> {
        List<String> pathnames = new ArrayList<>();
        List<String> filenames = Arrays.asList(walkPath.toFile().list(new ExtensionsFilenameFilter("jpg", "tif", "bmp")));
        filenames.forEach(fn -> {
            pathnames.add(String.format("%s/%s", walkPath.toFile().toString(), fn));
        });
        return pathnames;
    })
    .forEach(imagefiles::addAll);

    imagefiles.forEach(System.out::println);
}

【讨论】:

    【解决方案2】:

    要处理多个目录,您可以将它们流式传输并将它们平面映射到单个路径流。 要处理多个扩展名,您只需检查所有文件:

    public static List<String> multiWalk
        (Collection<String> directories, Collection<String> extensions) {
    
        return directories.stream()
                          .flatMap(d -> {
                              try {
                                  return Files.walk(Paths.get(d));
                              } catch (IOException e) {
                                  return Stream.empty();
                              }
                          })
                          .map(Object::toString)
                          .filter(f -> extensions.stream().anyMatch(f::endsWith))
                          .collect(Collectors.toList());
    }
    

    【讨论】:

    • 嗨@Mureinik,谢谢你的提议。我不得不像这样修改平面图部分:.flatMap(new Function&lt;String, Stream&lt;? extends Path&gt;&gt;() { @Override public Stream&lt;? extends Path&gt; apply(String d) { try { return Files.walk(Paths.get(d)); } catch (IOException ex) { Stream.empty(); } return null; } })
    • 因为编译器说:lambda body 既不是值也不是 void 兼容...
    • 或者更好...添加'return null;'陈述。我编辑了你的代码
    • @Cruxial 很可能 Mureinik 打算在 catch 块中使用 return Stream.empty(),尽管我个人会抛出 UncheckedIOException
    • 是的,我错过了那里的return。感谢您的编辑!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2021-12-28
    • 2011-06-06
    • 1970-01-01
    相关资源
    最近更新 更多