2011-03-04 18 views
68

ClassLoader.getResources()を使用して、クラスパスから再帰的なリソースを見つける方法を教えてください。ClassLoader.getResources()を正しく使用する方法は?

など。

META-INF "ディレクトリ" 内のすべてのリソースを見つけること
  • : は残念ながら、これが唯一の、まさにこの "ディレクトリ" にURLを取得んgetClass().getClassLoader().getResources("META-INF")

    よう

    何かを想像してみてください。

  • bla.xmlという名前のすべてのリソース(recursivly)

    getClass().getClassLoader().getResources("bla.xml")

    しかし、これは空Enumerationを返します。

ボーナス質問のように:どのようにClassLoader.getResources()ClassLoader.getResource()に違うのですか?

+12

@Andrew、フレームワークの多くは、反復のためにストライプのActionBeansやhibernate用のhbm.xmlファイルの検索など、いくつかのプロセスを自動化するアーカイブ内の名前や拡張子に基づいたファイル – bestsss

+2

http://stackoverflow.com/questions/1429172/how-do-i-list-the-files-inside-a-jar-file/ – Vadzim

+0

なぜあなたが混乱するのは、getResourcesがクラスローダーで動作することです。クラスパスに複数のJARを持つことができます。したがって、同じリソースを持つ複数のJARがある場合は、すべて取得します。ただし、ディレクトリ内を検索することは意図していません。 getResources( "META-INF")を使用すると、CLの検索パスにすべてのMETA-INFOディレクトリがあり、CLが単一のjarファイルクラスローダーの場合、最大で1つのエントリが取得されます。 – eckes

答えて

18

クラスパスを再帰的に検索する方法はありません。この方法でリソースを取得できるようにするには、リソースのフルパス名を知る必要があります。リソースは、ファイルシステム内のディレクトリまたはjarファイル内にある可能性があるため、「classpath」のディレクトリリストを実行するほど簡単ではありません。あなたはリソースの完全なパスを提供する必要があります。 '/com/mypath/bla.xml'。

2番目の質問では、getResourceは、指定されたリソース名と一致する最初のリソースを返します。クラスパスを検索する順序は、the javadoc for getResource.

+11

*クラスパスを再帰的に検索する方法はありません* ...もちろん可能です。例: 'URLClassLoader.getURLs()' JarFileを開き、反復します。 – bestsss

+3

@bestsss:URLがJarFileを指すのではなく、ディレクトリを指している場合はどうなりますか? – MRalwasser

+6

@bestsss、@MRalwasser:さらに悪いことに、HTTP URLを指している場合は? –

5

MRalwasserで与えられます。私はあなたにヒントを与えます。URL.getConnection()JarURLConnectionにキャストします。 次に、JarURLConnection.getJarFile()とvoilaを使用してください!あなたはJarFileを持っていて、内部のリソースには自由にアクセスできます。

残りはあなたに残します。

希望すると便利です。

+0

'URL.getConnection()'はどういう意味ですか?私はとにかくこの方法を見つけることができません。 – m0skit0

15

これは、特定のURLオブジェクトが指している先のファイルオブジェクトを取得するための最も簡単なワットです:内のすべてのリソースを見つけること

  • :あなたの具体的な質問のために、今すぐ

    File file=new File(url.toURI()); 
    

    をMETA-INF「ディレクトリ」:

BLAという名前のすべてのリソースこのURLに

Enumeration<URL> en=getClass().getClassLoader().getResources("META-INF"); 
if (en.hasMoreElements()) { 
    URL metaInf=en.nextElement(); 
    File fileMetaInf=new File(metaInf.toURI()); 

    File[] files=fileMetaInf.listFiles(); 
    //or 
    String[] filenames=fileMetaInf.list(); 
} 
  • を指しているFileオブジェクトを取得編。XML (recursivly)この場合

、あなたはいくつかのカスタムコードを行う必要があるでしょう。ここではダミーの例である:

final List<File> foundFiles=new ArrayList<File>(); 

FileFilter customFilter=new FileFilter() { 
    @Override 
    public boolean accept(File pathname) { 

     if(pathname.isDirectory()) { 
      pathname.listFiles(this); 
     } 
     if(pathname.getName().endsWith("bla.xml")) { 
      foundFiles.add(pathname); 
      return true; 
     } 
     return false; 
    } 

};  
//rootFolder here represents a File Object pointing the root forlder of your search 
rootFolder.listFiles(customFilter); 

コードが実行されると、あなたはfoundFiles一覧で見つかったすべてのocurrencesを取得します。ここで

+9

すべてのタイプのClassLoader(jarファイル内のクラスなど)のいずれの場合でもこれがうまくいくとは思えません – MRalwasser

+23

私はテストしましたが、例外が発生します:java.lang.IllegalArgumentException:URIが階層型ではありません。 "jar:..."のような不透明なURIからFileオブジェクトを作成することはできません – cn1h

9

はbestsss'回答に基づいてコードです:

Enumeration<URL> en = getClass().getClassLoader().getResources(
      "META-INF"); 
    List<String> profiles = new ArrayList<>(); 
    if (en.hasMoreElements()) { 
     URL url = en.nextElement(); 
     JarURLConnection urlcon = (JarURLConnection) (url.openConnection()); 
     try (JarFile jar = urlcon.getJarFile();) { 
      Enumeration<JarEntry> entries = jar.entries(); 
      while (entries.hasMoreElements()) { 
       String entry = entries.nextElement().getName(); 
       System.out.println(entry); 
      } 
     } 
    } 
+2

この種の構造は最初は混乱しています。 getClass()。getClassLoader()。getResources( "META-INF")の唯一の目的は、JarURLConnectionを取得するために使用するjarファイルの任意のファイルへの参照を取得することです。もともと、これはMETA-INFディレクトリ内のファイルを繰り返し処理すると考えていましたが、実際はjarファイル全体のすべてのファイルを繰り返し処理していました。 –

+0

それは私にとってはうまくいかない。 'J'は' getResources(path) 'メソッドに与えられた' path'で始まるエントリを含むように、クラスパスの最初のjarファイル 'J'の内容だけを表示します。 したがって、コードスニペットの結果は不完全であり、クラスパスの要素の順序によって異なります。 だから、@krockはそれが正しいと言っていました_クラスパスを再帰的に検索する方法はありません – Readren

31

ザ・春Frameworkは、再帰的にクラスパスを検索することを可能にするクラスを持っています

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 
resolver.getResources("classpath*:some/package/name/**/*.xml"); 
+0

jar内のリソースを解決しようとしていて、パターンがどのように見えるかわからない場合は、 'jar tf myjar.jar'。私は 'PathMatchinResourcePatternResolver("定義/ **/*。json ")'で終わった。 – MatrixManAtYrService