我正在開發一個多模塊Java項目,它由多個互相依賴的Eclipse項目組成,現在添加GUI主題支持我創建了一個不包含任何Java項目代碼,只是圖形用戶界面所需的圖標和圖片,我把它做成了一個Java項目,所以Maven會將它構建成一個.jar。現在有一個主要的應用程序將多個項目加載到主GUI中,該主GUI從當前實際模塊中的資源獲取其圖標。我想要做的就是從主應用程序的.jar的類路徑中包含的外部虛擬.jar文件中加載所有這些資源。目前爲止我發現的每種方法似乎都不起作用。 .jar不包含實際的java .class,所以沒有ClassLoader可供引用。有沒有其他方法可以在不提取.jar的情況下加載圖片?從java訪問外部.jar資源
回答
三樣東西,你可以嘗試:
- 創建資源罐子,你可以用它來獲取類加載器的參考虛擬類。
- 使用URLClassLoader,如果您知道,您的jar文件駐留在哪裏。
- 您始終可以通過擴展
java.lang.ClassLoader
來創建自己的ClassLoader。
對待外部JAR文件作爲一個zip壓縮文件並讀取圖像/資源是這樣的:
public ZipStuff(String filename) throws IOException
{
ZipFile zf = new ZipFile(filename);
Enumeration<? extends ZipEntry> entries = zf.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
ImageIcon ii = new ImageIcon(ImageIO.read(zf.getInputStream(ze)));
JLabel l = new JLabel(ii);
getContentPane().add(l);
}
setVisible(true);
pack();
}
在這種情況下,我有一個單一的圖像的jar文件,我加載到一個JLabel的。 ZipStuff類是一個JFrame。
你可以得到所有的資源(類路徑上所有jar文件應該工作,即使一個沒有班):
Enumeration<URL> resources = null;
try {
resources = Thread.currentThread().getContextClassLoader().getResources(someResource);
} catch (Exception ex) {
//no op
}
if (resources == null || !resources.hasMoreElements()) {
resources = ClasspathReader.class.getClassLoader().getResources(someResource);
}
然後檢查,看看目前的資源是文件。您可以將文件直接作爲文件處理。 但你的問題是關於jar文件,所以我不會去那裏。
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
if (resource.getProtocol().equals("file")) {
//if it is a file then we can handle it the normal way.
handleFile(resource, namespace);
continue;
}
此時你應該只罐子:文件資源,使... 分手了,看起來像這樣的字符串:
的jar:文件:/Users/rick/.m2/repository/調用/調用/ 1.0-SNAPSHOT /調用-1.0-SNAPSHOT.jar!/組織/節點/
這個
/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke -1.0-SNAPSHOT.jar
這
/組織/節點/
下面是代碼做討厭的錯誤檢查的上述不含。:)
String[] split = resource.toString().split(":");
String[] split2 = split[2].split("!");
String zipFileName = split2[0];
String sresource = split2[1];
System.out.printf("After split zip file name = %s," +
" \nresource in zip %s \n", zipFileName, sresource);
現在我們有zip文件名,所以我們可以閱讀:
ZipFile zipFile = new ZipFile(zipFileName);
現在,我們可以通過它的條目迭代:
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
/* If it is a directory, then skip it. */
if (entry.isDirectory()) {
continue;
}
String entryName = entry.getName();
System.out.printf("zip entry name %s \n", entryName);
看它是否與啓動我們正在尋找的資源。
if (!entryName.startsWith(someResource)) {
continue;
}
有兩個技巧我先前做的,看它是否是一個目錄
boolean isDir = !someResource.endsWith(".txt");
這隻能是因爲我在尋找與.TXT結尾的資源,我以爲,如果它不結束用.txt表示它是dir/foo/dir和/ foo/dir /都可以。
另一個訣竅是這樣的:
if (someResource.startsWith("/")) {
someResource = someResource.substring(1);
}
Classpath的資源永遠不能用一個開始斜線開始。從邏輯上講他們是這樣做的,但實際上你必須去掉它。這是類路徑資源的已知行爲。除非資源位於jar文件中,否則它使用斜槓。底線,通過剝離,它始終有效。
我們需要獲得織物的實際文件名。來自條目名稱的fileName部分。 其中/foo/bar/foo/bee/bar.txt,我們希望'bar.txt'是fileName。回到我們的while循環中。
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
...
String entryName = entry.getName(); //entry is zipEntry
String fileName = entryName.substring(entryName.lastIndexOf("/") + 1);
/** See if the file starts with our namespace and ends with our extension. */
if (fileName.startsWith(namespace) && fileName.endsWith(".txt")) {
接下來我們看看這些進入我們的標準相匹配,如果是讀取文件到System.out的內容。
try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
StringBuilder builder = new StringBuilder();
int ch = 0;
while ((ch = reader.read()) != -1) {
builder.append((char) ch);
}
System.out.printf("zip fileName = %s\n\n####\n contents of file %s\n###\n",
entryName, builder);
} catch (Exception ex) {
ex.printStackTrace();//it is an example/proto :)
}
}
你可以在這裏看到完整的例子:Sleepless in Pleasanton。
- 1. 訪問JAR資源
- 2. 訪問JAR資源
- 3. 訪問外部資源
- 4. Java jar無法訪問資源
- 5. 如何使用spring訪問外部jar文件中的資源?
- 6. 在JAR中訪問資源
- 7. 訪問JAR中的資源
- 8. 訪問JAR中的資源
- 9. 防止訪問jar資源
- 10. 從jar裏面訪問資源
- 11. 從jar中訪問網絡資源
- 12. 從jar共享庫訪問資源
- 13. Java -jar:訪問外部配置文件
- 14. 訪問iText中的外部URL資源
- 15. 訪問外部資源與PhoneGap的
- 16. Spring WebContent資源 - 訪問ServletContext外部
- 17. 在jar外部加載資源文件
- 18. 訪問外部源
- 19. 我可以從資源外部訪問清單內的資源屬性嗎?
- 20. 在JAR文件中訪問資源
- 21. exportet jar文件不會訪問資源
- 22. 從restlet中訪問ServletContext的Java資源
- 23. 從外部創建的.resx文件訪問資源
- 24. 如何從網站訪問外部資源Aspx
- 25. 如何從外部程序集訪問資源
- 26. 從外部程序包訪問Android資源
- 27. C#資源文件 - 如何從XAML訪問內部資源?
- 28. 訪問HSQLDB「資源」捆綁數據庫中的jar資源是
- 29. 從外部源訪問本地主機
- 30. 在JAR內部訪問Java資源會返回大約75%的垃圾
這個問題看起來像http://stackoverflow.com/questions/403256/how-do-i-read-a-resource-file-from-a-java-jar-file – Kappei 2012-04-16 14:58:38
的副本*「他說。罐子不包含任何實際的Java .classes,所以沒有ClassLoader的引用。「*如果罐是應用程序的運行時類路徑中,資源應該使用的getResource()(在上下文類加載器中找到)用「從根路徑」,如'/路徑/到/ the.png' – 2012-04-16 14:59:36
它實際上是在我的部分簡單的錯誤(I使用一個不存在的路徑)。顯然,Java有從classpath中搶奪資源,無論身在何處的getResource()是由所謂的沒有問題。有人向我解釋說,Java在運行時基本上用所有使用過的jar構建了一個文件系統,因此訪問非常簡單並且可以在全球範圍內使用。感謝大家的建議! – user1307791 2012-04-20 18:06:56