如何获取 Java JAR 文件中资源的路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/941754/
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
How to get a path to a resource in a Java JAR file
提问by no_ripcord
I am trying to get a path to a Resource but I have had no luck.
我正在尝试获取资源的路径,但我没有运气。
This works (both in IDE and with the JAR) but this way I can't get a path to a file, only the file contents:
这有效(在 IDE 和 JAR 中),但这样我无法获得文件的路径,只能获得文件内容:
ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
If I do this:
如果我这样做:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());
The result is:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
结果是:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
Is there a way to get a path to a resource file?
有没有办法获取资源文件的路径?
采纳答案by Neal Maloney
This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.
这是故意的。“文件”的内容可能无法作为文件使用。请记住,您正在处理可能是 JAR 文件或其他类型资源的一部分的类和资源。类加载器不必为资源提供文件句柄,例如 jar 文件可能尚未扩展为文件系统中的单个文件。
Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.
如果绝对需要 java.io.File,则可以通过将流复制到临时文件中并执行相同操作来通过获取 java.io.File 来完成任何操作。
回答by cd1
if netclient.p
is inside a JAR file, it won't have a path because that file is located inside other file. in that case, the best path you can have is really file:/path/to/jarfile/bot.jar!/config/netclient.p
.
如果netclient.p
在 JAR 文件中,它不会有路径,因为该文件位于其他文件中。在这种情况下,您可以拥有的最佳路径是file:/path/to/jarfile/bot.jar!/config/netclient.p
.
回答by fortran
A File is an abstraction for a file in a filesystem, and the filesystems don't know anything about what are the contents of a JAR.
文件是文件系统中文件的抽象,文件系统对 JAR 的内容一无所知。
Try with an URI, I think there's a jar:// protocol that might be useful for your purpouses.
尝试使用 URI,我认为有一个 jar:// 协议可能对您的目的有用。
回答by eric manley
You need to understand the path within the jar file.
Simply refer to it relative. So if you have a file (myfile.txt), located in foo.jar under the \src\main\resources
directory (maven style). You would refer to it like:
您需要了解 jar 文件中的路径。
简单地参考它相对。所以如果你有一个文件(myfile.txt),位于foo.jar\src\main\resources
目录下(maven风格)。你会像这样引用它:
src/main/resources/myfile.txt
If you dump your jar using jar -tvf myjar.jar
you will see the output and the relative path within the jar file, and use the FORWARD SLASHES.
如果您使用转储 jar,jar -tvf myjar.jar
您将看到 jar 文件中的输出和相对路径,并使用 FORWARD SLASHES。
回答by DeProgrammer
I spent a while messing around with this problem, because no solution I found actually worked, strangely enough! The working directory is frequently not the directory of the JAR, especially if a JAR (or any program, for that matter) is run from the Start Menu under Windows. So here is what I did, and it works for .class files run from outside a JAR just as well as it works for a JAR. (I only tested it under Windows 7.)
我花了一段时间来解决这个问题,因为我发现没有一个真正有效的解决方案,奇怪的是!工作目录通常不是 JAR 的目录,尤其是在 Windows 下从“开始”菜单运行 JAR(或任何程序)时。所以这就是我所做的,它适用于从 JAR 外部运行的 .class 文件,就像它适用于 JAR。(我只在 Windows 7 下测试过。)
try {
//Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
//Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
//Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.
//Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
try {
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
} catch (Exception e) { }
//Find the last / and cut it off at that location.
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
//If it starts with /, cut it off.
if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
//If it starts with file:/, cut that off, too.
if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
PROGRAM_DIRECTORY = ""; //Current working directory instead.
}
回答by Anatoly
The following path worked for me: classpath:/path/to/resource/in/jar
以下路径对我有用: classpath:/path/to/resource/in/jar
回答by Tombart
When loading a resource make sure you notice the difference between:
加载资源时,请确保您注意到以下区别:
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path
and
和
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning
I guess, this confusion is causing most of problems when loading a resource.
我想,在加载资源时,这种混乱会导致大多数问题。
Also, when you're loading an image it's easier to use getResourceAsStream()
:
此外,当您加载图像时,它更易于使用getResourceAsStream()
:
BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));
When you really have to load a (non-image) file from a JAR archive, you might try this:
当您真的必须从 JAR 存档中加载(非图像)文件时,您可以尝试以下操作:
File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile("tempfile", ".tmp");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.close();
file.deleteOnExit();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if (file != null && !file.exists()) {
throw new RuntimeException("Error: File " + file + " not found!");
}
回答by Vilnis Krumins
When in a jar file, the resource is located absolutely in the package hierarchy (not file system hierarchy). So if you have class com.example.Sweet loading a resource named "./default.conf" then the resource's name is specified as "/com/example/default.conf".
在 jar 文件中时,资源绝对位于包层次结构(而不是文件系统层次结构)中。因此,如果您让 com.example.Sweet 类加载名为“./default.conf”的资源,则该资源的名称将指定为“/com/example/default.conf”。
But if it's in a jar then it's not a File ...
但是如果它在一个罐子里,那么它就不是一个文件......
回答by Shano
private static final String FILE_LOCATION = "com/input/file/somefile.txt";
//Method Body
InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);
Getting this from getSystemResourceAsStream
is the best option. By getting the inputstream rather than the file or the URL, works in a JAR file and as stand alone.
得到这个getSystemResourceAsStream
是最好的选择。通过获取输入流而不是文件或 URL,可以在 JAR 文件中独立工作。
回答by Manojkumar Khotele
The one line answer is -
单行答案是——
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()
Basically getResource
method gives the URL.
From this URL you can extract the path by calling toExternalForm()
基本上getResource
方法给出了 URL。从此 URL 中,您可以通过调用来提取路径toExternalForm()
References:
参考: