加载一个存储在Jar包中的资源。

22

在我的应用程序中,我以这种方式加载资源:

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

这样会给我:

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

当我从IDE运行我的应用程序时,它可以正常工作,但是当我运行应用程序的jar包时:

java -jar app.jar
路径变为:
jar:/root/app.jar!/repository

有没有办法解决这个问题?

我将使用“repository”目录名称来创建它:

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

同样地,我会得到一个文件名(而不是一个目录),然后这样使用它:

System.setProperty("javax.net.ssl.trustStore", fileNameString)
3个回答

35

看起来你是想使用FileInputStream之类的方式加载资源。不要这样做:不要调用getResource,而应该调用getResourceAsStream方法并从中读取数据。

(你也可以从URL中加载资源,但调用getResourceAsStream更加方便。)

编辑:看到你更新后的回答,似乎其他代码依赖于数据在文件系统中作为单个物理文件。因此,答案就不是首先将其捆绑在JAR文件中。你可以检查它是否位于单独的文件中,如果不是,则将其提取到临时文件中,但在我看来这种方法相当不稳定。


1
同意。无论何时,只要您不能百分之百地确定您将处理物理单个文件(例如Java Web Start),您应始终使用流进行编码。 - Thorbjørn Ravn Andersen

8
当使用java -jar app.jar运行代码时,Java仅使用JAR文件清单中定义的类路径(即Class-Path属性)。如果类在app.jar中,或者类在JAR的清单的Class-Path属性设置的类路径中,您可以使用以下代码片段加载该类,其中className是完全限定的类名。
final String classAsPath = className.replace('.', '/') + ".class";
final InputStream input = ClassLoader.getSystemResourceAsStream( path/to/class );

现在,如果该类不是JAR的一部分,并且它也没有在清单文件的Class-Path中列出,那么类加载器将无法找到它。相反,您可以使用URLClassLoader,但需要注意处理Windows和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 );

在这两个示例中,您需要处理异常以及如果找不到资源,则输入流为null的事实。此外,如果您需要将InputStream转换为byte[],您可以使用Apache的commons IOUtils.toByteArray(...)。而且,如果您想要一个Class,您可以使用类加载器的defineClass(...)方法,该方法接受byte[]
您可以在Diffusive源代码中的ClassLoaderUtils类中找到此代码,您可以在SourceForge上的github.com/robphilipp/diffusive找到它。
还有一个方法可以从相对路径和绝对路径创建Windows和Unix / Linux / MacOSX的URL,位于RestfulDiffuserManagerResource.createJarClassPath(...)中。

5

构建一个URL,然后可以使用openStream方法来加载资源(甚至在jar文件中)。


1
这就是 getResourceAsStream 的作用。 - Matthias B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接