Java 加载包含在 jar 中的资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/574809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:23:55  来源:igfitidea点击:

Load a resource contained in a jar

javajarresources

提问by Giancarlo

In my application I load resources in this manner:

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

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

and this gives me:

这给了我:

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

This works fine when I run my application from the IDE, but when I run the jar of my application:

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

java -jar app.jar

The path becomes:

路径变为:

jar:/root/app.jar!/repository

is there any way to solve this problem?

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

I'll use the "repository" dir name in order to create this:

我将使用“存储库”目录名称来创建它:

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

In the same manner, I'll get one file name (instead of a dir) and I'll use it this way:

以同样的方式,我会得到一个文件名(而不是目录),我会这样使用它:

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

采纳答案by Jon Skeet

It sounds like you're then trying to load the resource using a FileInputStreamor something like that. Don't do that: instead of calling getResource, call getResourceAsStreamand read the data from that.

听起来您正在尝试使用 aFileInputStream或类似方法加载资源。不要那样做:不要调用getResource,而是调用getResourceAsStream并从中读取数据。

(You could load the resources from the URL instead, but calling getResourceAsStreamis a bit more convenient.)

(您可以改为从 URL 加载资源,但调用getResourceAsStream更方便一些。)

EDIT: Having seen your updated answer, it seems other bits of code rely on the data being in a physical single file in the file system. The answer is therefore not to bundle it in a jar file in the first place. You couldcheck whether it's in a separate file, and if not extract it to a temporary file, but that's pretty hacky IMO.

编辑:看到您更新的答案后,似乎其他代码位依赖于文件系统中物理单个文件中的数据。因此,答案是首先不要将其捆绑在 jar 文件中。您可以检查它是否在一个单独的文件中,如果没有将其解压缩到一个临时文件中,但这在 IMO 中非常棘手。

回答by Konrad Rudolph

Construct a URL, you can then load a resource (even in a jar file) using the openStreammethod.

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

回答by Rob Philipp

When running code using java -jar app.jar, java uses ONLY the class path defined in the manifest of the JAR file (i.e. Class-Pathattribute). If the class is in app.jar, or the class is in the class path set in the Class-Pathattribute of the JAR's manifest, you can load that class using the following code snippet, where the classNameis the fully-qualified class name.

使用 运行代码时java -jar app.jar,java 仅使用 JAR 文件清单中定义的类路径(即Class-Path属性)。如果类位于 中app.jar,或者类位于Class-PathJAR 清单的属性中设置的类路径中,则可以使用以下代码片段加载该类,其中className是完全限定的类名。

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

Now if the class is not part of the JAR, and it isn't in the manifest's Class-Path, then the class loader won't find it. Instead, you can use the URLClassLoader, with some care to deal with differences between windows and Unix/Linux/MacOSX.

现在,如果该类不是 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 );

In both examples you'll need to deal with the exceptions, and the fact that the input stream is nullif the resource can't be found. Also, if you need to get the InputStreaminto a byte[], you can use Apache's commons IOUtils.toByteArray(...). And, if you then want a Class, you can use the class loader's defineClass(...)method, which accepts the byte[].

在这两个示例中,您都需要处理异常,以及null无法找到资源时输入流的事实。此外,如果您需要InputStream进入byte[],您可以使用 Apache 的 commons IOUtils.toByteArray(...)。并且,如果您想要一个Class,您可以使用类加载器的defineClass(...)方法,该方法接受byte[].

You can find this code in a ClassLoaderUtilsclass in the Diffusive source code, which you can find on SourceForge at github.com/robphilipp/diffusive

您可以ClassLoaderUtils在 Diffusive 源代码的类中找到此代码,您可以在 SourceForge 上找到该代码,网址为 github.com/robphilipp/diffusive

And a method to create URL for Windows and Unix/Linux/MacOSX from relative and absolute paths in RestfulDiffuserManagerResource.createJarClassPath(...)

以及从相对和绝对路径为 Windows 和 Unix/Linux/MacOSX 创建 URL 的方法 RestfulDiffuserManagerResource.createJarClassPath(...)