Load một tài nguyên chứa trong một lọ


21

Trong ứng dụng của tôi, tôi tải các tài nguyên theo cách này:

WinProcessor.class.getResource("repository").toString(); 

và điều này mang lại cho tôi:

file:/root/app/repository (and I replace "file:" with empty string) 

này hoạt động tốt khi tôi chạy ứng dụng của tôi từ IDE , nhưng khi tôi chạy jar của ứng dụng của tôi:

java -jar app.jar 

Con đường trở thành:

jar:/root/app.jar!/repository 

có cách nào để giải quyết vấn đề này không?

tôi sẽ sử dụng các "kho" tên dir nhằm tạo này:

ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null); 

Trong cùng một cách thức, tôi sẽ nhận được một tên file (thay vì một dir) và tôi sẽ sử dụng nó theo cách này:

System.setProperty("javax.net.ssl.trustStore", fileNameString) 
35

Có vẻ như bạn đang cố gắng tải tài nguyên bằng cách sử dụng FileInputStream hoặc nội dung tương tự. Đừng làm điều đó: thay vì gọi số getResource, hãy gọi getResourceAsStream và đọc dữ liệu từ đó.

(Bạn có thể tải các nguồn lực từ các URL thay vào đó, nhưng gọi getResourceAsStream là thuận tiện hơn một chút.)

EDIT: Có nhìn thấy câu trả lời cập nhật của bạn, có vẻ như bit khác của mã dựa trên các dữ liệu được trong một tệp đơn vật lý trong hệ thống tệp. Do đó, câu trả lời là không bó nó vào một tệp jar ngay từ đầu. Bạn có thể kiểm tra xem nó có nằm trong một tệp riêng biệt hay không và nếu không giải nén nó vào một tệp tạm thời, nhưng đó là IMO khá hacky.

+1

Đồng ý. Bất cứ khi nào bạn không thể nói với 100% chắc chắn rằng bạn sẽ đối phó với các tập tin vật lý duy nhất (java web bắt đầu cho một), bạn nên luôn luôn mã với suối. 22 feb. 092009-02-22 12:16:38


5

Xây dựng một URL, sau đó bạn có thể tải một nguồn lực (ngay cả trong một file jar) bằng cách sử dụng phương pháp openStream.

+1

Đó là những gì 'getResourceAsStream' thực hiện. 12 jul. 162016-07-12 14:20:56


9

Khi chạy mã sử dụng java -jar app.jar, java chỉ sử dụng đường dẫn lớp được xác định trong tệp kê khai của tệp JAR (tức là thuộc tính Class-Path). Nếu lớp là trong app.jar hoặc lớp nằm trong đường dẫn lớp được đặt trong thuộc tính Class-Path của tệp kê khai JAR, bạn có thể tải lớp đó bằng đoạn mã sau, trong đó className là tên lớp đủ điều kiện.

final String classAsPath = className.replace('.', '/') + ".class"; 
final InputStream input = ClassLoader.getSystemResourceAsStream(path/to/class); 

Bây giờ nếu lớp học không nằm trong JAR và không nằm trong tệp kê khai Class-Path thì trình tải lớp sẽ không tìm thấy. Thay vào đó, bạn có thể sử dụng các URLClassLoader, với một số chăm sóc để đối phó với sự khác biệt giữa các cửa sổ và Unix/Linux/MacOSX.

// the class to load 
final String classAsPath = className.replace('.', '/') + ".class"; 

// the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below) 
final URL url = new URL("file", null, "///C:/Users/diffusive/app.jar"); 
//final URL url = new URL("file", null, "/Users/diffusive/app.jar"); 

// create the class loader with the JAR file 
final URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { url }); 

// grab the resource, through, this time from the `URLClassLoader` object 
// rather than from the `ClassLoader` class 
final InputStream input = urlClassLoader.getResourceAsStream(classAsPath); 

Trong cả hai ví dụ bạn sẽ cần phải đối phó với những trường hợp ngoại lệ, và thực tế là dòng đầu vào là null nếu tài nguyên không thể được tìm thấy. Ngoài ra, nếu bạn cần lấy số InputStream vào số byte[], bạn có thể sử dụng số commons IOUtils.toByteArray(...) của Apache. Và, nếu bạn muốn có một Class, bạn có thể sử dụng phương thức defineClass(...) của trình tải lớp, chấp nhận byte[].

Bạn có thể tìm thấy mã này trong một lớp học ClassLoaderUtils trong mã nguồn khuếch tán, mà bạn có thể tìm thấy trên SourceForge tại github.com/robphilipp/diffusive

Và một phương pháp để tạo URL cho Windows và Unix/Linux/MacOSX từ đường dẫn tương đối và tuyệt đối trong RestfulDiffuserManagerResource.createJarClassPath(...)