10

指定された Ant のようなパターンに一致するファイルのリストを提供するメソッドを提供するライブラリを探しています。

*foo/**/*.txt私が得るために

foo/x.txt
foo/bar/baz/.txt
myfoo/baz/boo/bar.txt

など。DirWalker と

PathMatcher mat = FileSystems.getDefault().getPathMatcher("glob:" + filesPattern);

、しかし、私はいくつかの管理されたlibをむしろ望んでいます。Commons IO にはそれがあると思っていましたが、ありませんでした。

更新: Ant のコードを再利用することに満足していますが、Ant 全体よりも小さいものを好むでしょう。

4

3 に答える 3

3

そのため、速度のためにアプリのサイズを数 MB 犠牲にして、最終的にAntDirectoryScannerを使用しました。

また、Spring のPathMatchingResourcePatternResolverもあります。

//files = new PatternDirWalker( filesPattern ).list( baseDir );
files = new DirScanner( filesPattern ).list( baseDir );


public class DirScanner {

    private String pattern;

    public DirScanner( String pattern ) {
        this.pattern = pattern;
    }

    public List<File> list( File dirToScan ) throws IOException {

            DirectoryScanner ds = new DirectoryScanner();
            String[] includes = {  this.pattern };
            //String[] excludes = {"modules\\*\\**"};
            ds.setIncludes(includes);
            //ds.setExcludes(excludes);
            ds.setBasedir( dirToScan );
            //ds.setCaseSensitive(true);
            ds.scan();

            String[] matches = ds.getIncludedFiles();
            List<File> files = new ArrayList(matches.length);
            for (int i = 0; i < matches.length; i++) {
                files.add( new File(matches[i]) );
            }
            return files;
    }

}// class

そして、これが私がコードを書き始めた私の実装であり、完成していません。アイデアは、パターンのスタックを保持し、dir ツリーをトラバースし、内容を実際のスタックの深さと比較し、**.

しかし、私はPathMatcherAnt の impl に頼りました。

public class PatternDirWalker {
    //private static final Logger log = LoggerFactory.getLogger( PatternDirWalker.class );

    private String pattern;
    private List segments;
    private PathMatcher mat;

    public PatternDirWalker( String pattern ) {
        this.pattern = pattern;
        this.segments = parseSegments(pattern);
        this.mat = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
    }

    public List<File> list( File dirToScan ) throws IOException{

        return new DirectoryWalker() {
            List<File> files = new LinkedList();

            @Override protected void handleFile( File file, int depth, Collection results ) throws IOException {
                if( PatternDirWalker.this.mat.matches( file.toPath()) )
                    results.add( file );
            }

            public List<File> findMatchingFiles( File dirToWalk ) throws IOException {
                this.walk( dirToWalk, this.files );
                return this.files;
            }
        }.findMatchingFiles( dirToScan );

    }// list()

    private List<Segment> parseSegments( String pattern ) {
        String[] parts = StringUtils.split("/", pattern);
        List<Segment> segs = new ArrayList(parts.length);
        for( String part : parts ) {
            Segment seg = new Segment(part);
            segs.add( seg );
        }
        return segs;
    }

    class Segment {
        public final String pat;  // TODO: Tokenize
        private Segment( String pat ) {
            this.pat = pat;
        }
    }

}// class
于 2013-06-05T03:06:02.730 に答える
0

Google Guavaには、ディレクトリ内のファイルの深さ優先および幅優先の列挙を可能にするファイル用の TreeTraverser があります。次に、ファイル名の正規表現に基づいて結果をフィルタリングするか、その他必要なことを行うことができます。

以下に例を示します (Guava が必要です)。

import java.io.File;
import java.util.List;
import java.util.regex.Pattern;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.io.Files;
import com.google.common.collect.Iterables;
import com.google.common.collect.TreeTraverser;

public class FileTraversalExample {

  private static final String PATH = "/path/to/your/maven/repo";
  private static final Pattern SEARCH_PATTERN = Pattern.compile(".*\\.jar");

  public static void main(String[] args) {
    File directory = new File(PATH);
    TreeTraverser<File> traverser = Files.fileTreeTraverser();
    Iterable<String> allFiles = Iterables.transform(
        traverser.breadthFirstTraversal(directory),
        new FileNameProducingPredicate());
    Iterable<String> matches = Iterables.filter(
      allFiles,
      Predicates.contains(SEARCH_PATTERN));
    System.out.println(matches);
  }

  private static class FileNameProducingPredicate implements Function<File, String> {
    public String apply(File input) {
      return input.getAbsolutePath();
    }
  }

}

Guava では、Iterables.filter を使用して任意の Predicate でフィルター処理できるため、必要がなければパターンを使用する必要はありません。

于 2015-03-23T08:02:50.683 に答える