2016-09-03 3 views
3
私は、次のオプション/パラメータを使用してJavaでファイルスキャナを開発する必要があり

グロブ理解

  1. 一つのディレクトリ* .xmlファイル、* .TXT、*のtest.CSV
  2. よう
  3. つまたは複数のパターン 再帰スキャンのための
  4. スイッチ

私は最善の方法は、このようなものになるだろうと思う:

public class FileScanningTest { 

    public static void main(String[] args) throws IOException { 

     String directory = "C:\\tmp\\scanning\\"; 
     String glob  = "**/*.xml"; 
     Boolean rekursiv = false; 

     final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:"+glob); 

     Files.walkFileTree(Paths.get(directory), new SimpleFileVisitor<Path>() { 

      @Override 
      public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { 
       if (pathMatcher.matches(path)) { 
        System.out.println(path); 
       } 
       return FileVisitResult.CONTINUE; 
      } 

      @Override 
      public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { 
       return FileVisitResult.CONTINUE; 
      } 
     }); 

    } 

} 

なぜ私は実際のパターンの前に "** /"を入れなければならないのか分かりません。また、スキャンを再帰的にします。 ** /を削除すると、アプリケーションはもう何も見つけられません。

https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#globは、再帰的であることを示していますが、削除しても機能しないのはなぜですか?

誰かが私にヒントを与えることができますか?

みんなありがとうとは、素敵な週末に

***の違いは *は、ディレクトリの区切りを( /\は、お使いのOSによって異なります)と一致しないことである

答えて

2

ディレクトリ/tmp/scanning/から始まるglobを使用して、再帰的に*.xmlを見つけるには、このサンプルを見てください。それはLinux Ubuntuで動作し、あなたが望むことをします。これはUnix findユーティリティのように動作します。私はUbuntu以外のOSでテストしませんでしたが、ファイル名の区切り文字を変更するだけですみます。

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.*; 


public class FileScanningTest { 

    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; 
     } 
    } 


    public static void main(String[] args) 
      throws IOException { 
     boolean recursive = false; 
     Path startingDir = Paths.get("/tmp/scanning"); 
     String pattern = "*.{html,xml}"; 

     Finder finder = new Finder(pattern); 
     if (!recursive) { 
      Path dir = startingDir; 
      List<File> files = new ArrayList<>(); 
      try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{xml,html}")) { 
       for (Path entry : stream) { 
        files.add(entry.toFile()); 
       } 

       for (File xmlfile : files) { 
        System.out.println(xmlfile); 
       } 
      } catch (IOException x) { 
       throw new RuntimeException(String.format("error reading folder %s: %s", 
         dir, 
         x.getMessage()), 
         x); 
      } 
     } else {  
      Files.walkFileTree(startingDir, finder); 
      finder.done(); 
     } 

    } 
} 

テスト

~> java FileScanningTest 
/tmp/scanning/dir2/test2.xml 
/tmp/scanning/blah.xml 
Matched: 2 

あなたが*.xmltest3.htmlのいずれかに一致するようにしたい場合は、このパターンを使用することができます。詳細については、String pattern = "{*.xml,test3.html}";

+0

ありがとうございます。これはWindowsプラットフォームでも機能します。 しかし再帰スキャンを無効にするにはどうすればよいですか?再帰スキャンを無効にするオプションがあります。同時にいくつかの異なるパターンを持つ方法がありますか? – Hauke

+0

@ Haukeはい。再帰スキャンを無効にするには、ユーザーからのオプションが必要です。 'args [0]'であり、正規表現でいくつかの異なるパターンを使うことができます。私はあなたを見せたり、新しい質問をすることができます。あなたの仕様に従って投稿したコードを更新できます。私はまた、これがJavaでどのように行われているかを学ぶのが好きです(私はC言語で多くしています)。 –

+1

あなたのコードを更新することができればそれは素晴らしいでしょう。これは単なるテストクラスで、アプリケーションの引数を解析するのではなく、 "再帰的"なブールフラグを付けても問題ありません。あなたの助けをありがとう – Hauke

1

が、**意志を持っています。このようなファイルツリーを考える:パターン**a.xmlが一致する一方、(それは/が含まれているためではない​​)

a/ 
    b.xml 
c/ 
    a.xml 
da.xml 

パターン*a.xmlのみda.xmlにマッチします両方da.xmlと​​、およびパターンa**.xmla/b.xmlにマッチします。

+0

感謝を。つまり、パス全体を指定せずにディレクトリにすでに存在する場合、パターン* a.xmlのみを使用できますか? – Hauke