2011-03-04 39 views
68

Làm cách nào để sử dụng ClassLoader.getResources() để tìm tài nguyên đệ quy từ đường dẫn lớp của tôi?Làm thế nào để sử dụng ClassLoader.getResources() một cách chính xác?

Ví dụ:

  • tìm mọi nguồn lực trong "thư mục" META-INF: Hãy tưởng tượng một cái gì đó giống như

    getClass().getClassLoader().getResources("META-INF")

    Thật không may, điều này không chỉ lấy một URL chính xác này "thư mục".

  • mọi nguồn lực tên bla.xml (recursivly)

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

    Nhưng điều này trả về một sản phẩm nào Enumeration.

Và làm câu hỏi thưởng: ClassLoader.getResources() khác với ClassLoader.getResource() như thế nào?

+12

@ Andrew, rất nhiều các khuôn khổ lặp cho một số tệp dựa trên tên hoặc phần mở rộng trong lưu trữ để tự động hóa một số quy trình, như tìm kiếm ActionBeans of Stripes hoặc tệp hbm.xml cho ngủ đông. – bestsss

+2

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

+0

Tiếng vang tại sao nó gây nhầm lẫn cho bạn là getResources hoạt động trên bộ nạp lớp có thể có nhiều JAR trong classpath. Vì vậy, nếu bạn có nhiều JAR với cùng một tài nguyên, bạn sẽ có được tất cả. Tuy nhiên nó không có ý định tìm kiếm các thư mục bên trong. Với getResources ("META-INF"), bạn nhận được tất cả các thư mục META-INFO trong đường dẫn tìm kiếm của CL và nếu CL là một trình nạp lớp tệp jar đơn, bạn sẽ nhận được một mục nhập. – eckes

Trả lời

18

Không có cách nào để tìm kiếm đệ quy thông qua đường dẫn lớp. Bạn cần biết tên đường dẫn đầy đủ của một tài nguyên để có thể truy xuất nó theo cách này. Tài nguyên có thể nằm trong một thư mục trong hệ thống tệp hoặc trong một tệp jar để nó không đơn giản như thực hiện một danh sách thư mục của "classpath". Bạn sẽ cần cung cấp đường dẫn đầy đủ của tài nguyên, ví dụ: '/com/mypath/bla.xml'.

Đối với câu hỏi thứ hai của bạn, getResource sẽ trả lại tài nguyên đầu tiên khớp với tên tài nguyên đã cho. Thứ tự mà đường dẫn lớp được tìm kiếm được cung cấp trong the javadoc for getResource.

+11

* Không có cách nào để tìm kiếm đệ quy thông qua các classpath * ... Chắc chắn, nó có thể. Ví dụ: 'URLClassLoader.getURLs()'. Mở JarFile, lặp lại. – bestsss

+3

@bestsss: nếu URL không trỏ đến JarFile, nhưng vào một thư mục thì sao? – MRalwasser

+6

@bestsss, @MRalwasser: hoặc thậm chí tệ hơn, nếu nó trỏ đến url HTTP? –

5

MRalwasser, tôi sẽ cung cấp cho bạn một gợi ý, hãy đúc URL.getConnection() đến JarURLConnection. Sau đó sử dụng JarURLConnection.getJarFile() và thì đấy! Bạn có JarFile và bạn được tự do truy cập các tài nguyên bên trong.

Phần còn lại tôi để lại cho bạn.

Hy vọng điều này sẽ hữu ích!

+0

Bạn có ý gì với 'URL.getConnection()'? Tôi không thể tìm thấy phương pháp này anyway. – m0skit0

15

Đây là wat đơn giản nhất để có được những đối tượng tập tin mà một đối tượng URL nào đó được chỉ vào:

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

Bây giờ, mọi thắc mắc cụ thể của bạn:

  • tìm mọi nguồn lực trong thư mục META-INF ":

Bạn có thể sử dụng ed được trỏ đối tượng File để URL này

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(); 
} 
  • mọi nguồn lực tên bla.xml (recursivly)

Trong trường hợp này, bạn sẽ phải làm một số mã tùy chỉnh. Dưới đây là ví dụ giả:

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

Khi mã được chạy, bạn sẽ nhận được tất cả các ocurrences tìm thấy tại Danh sách foundFiles.

+9

Tôi nghi ngờ rằng điều này sẽ làm việc trong mọi trường hợp đối với mọi loại ClassLoaders (ví dụ: các lớp trong các tệp jar) – MRalwasser

+23

Tôi đã thử nghiệm, tôi nhận được một ngoại lệ: java.lang.IllegalArgumentException: URI không phải là phân cấp. Bạn không thể tạo đối tượng Tệp từ URI mờ như "jar: ..." – cn1h

9

Dưới đây là mã dựa trên câu trả lời 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

Cấu trúc của kiểu này làm tôi bối rối lúc đầu. Nó có vẻ như là mục đích duy nhất của getClass() getClassLoader() getResources ("META-INF") là lấy một tham chiếu đến một số tệp tùy ý trong jar, mà sau đó chúng ta sử dụng để lấy JarURLConnection. Ban đầu tôi nghĩ rằng điều này sẽ lặp lại trên các tệp trong thư mục META-INF, nhưng nó thực sự lặp lại trên mỗi tệp trong toàn bộ nhóm. –

+0

Nó không hiệu quả với tôi. Nó chỉ hiển thị nội dung của tệp jar đầu tiên 'J' trong đường dẫn lớp sao cho' J' chứa một mục bắt đầu bằng 'đường dẫn' được đưa ra cho phương thức' getResources (path) '. Vì vậy, kết quả của đoạn mã của bạn chưa hoàn thành và phụ thuộc vào thứ tự của các phần tử trong đường dẫn lớp. Vì vậy, @krock đã đúng khi anh ấy nói rằng _Không có cách nào để tìm kiếm đệ quy thông qua classpath_ – Readren

31

Các Spring Framework có một lớp cho phép đệ quy tìm kiếm thông qua classpath:

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

Nếu bạn đang cố gắng giải quyết tài nguyên bên trong một cái bình và bạn không chắc chắn mẫu sẽ trông như thế nào, hãy chạy 'jar tf myjar.jar'. Tôi đã kết thúc với 'PathMatchinResourcePatternResolver (" định nghĩa/**/*. Json ")'. – MatrixManAtYrService

Các vấn đề liên quan