我正在开发一个多模块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