Java 从 jar 中读取资源文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20389255/
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
Reading a resource file from within jar
提问by PrinceCJC
I would like to read a resource from within my jar like so:
我想从我的 jar 中读取资源,如下所示:
File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));
//Read the file
and it works fine when running it in Eclipse, but if I export it to a jar the run it there is an IllegalArgumentException:
在 Eclipse 中运行它时它工作正常,但是如果我将它导出到一个 jar 中运行它会有一个 IllegalArgumentException:
Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical
and I really don't know why but with some testing I found if I change
我真的不知道为什么但是通过一些测试我发现如果我改变
file = new File(getClass().getResource("/file.txt").toURI());
to
到
file = new File(getClass().getResource("/folder/file.txt").toURI());
then it works the opposite (it works in jar but not eclipse).
然后它的工作方式相反(它在 jar 中工作,但在 eclipse 中不工作)。
I'm using Eclipse and the folder with my file is in a class folder.
我正在使用 Eclipse,我的文件所在的文件夹位于类文件夹中。
采纳答案by Drew MacInnis
Rather than trying to address the resource as a Filejust ask the ClassLoaderto return an InputStreamfor the resource instead via getResourceAsStream:
与其尝试将资源作为文件寻址,不如让ClassLoader通过getResourceAsStream返回资源的InputStream:
InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
As long as the file.txt
resource is available on the classpath then this approach will work the same way regardless of whether the file.txt
resource is in a classes/
directory or inside a jar
.
只要file.txt
资源在类路径上可用,那么无论file.txt
资源是在classes/
目录中还是在jar
.
The URI is not hierarchical
occurs because the URI for a resource within a jar file is going to look something like this: file:/example.jar!/file.txt
. You cannot read the entries within a jar
(a zip
file) like it was a plain old File.
的URI is not hierarchical
,因为一个jar文件中的资源的URI是要看起来像这样出现:file:/example.jar!/file.txt
。您无法读取jar
(zip
文件)中的条目,就像它是一个普通的旧File。
This is explained well by the answers to:
对以下问题的回答很好地解释了这一点:
回答by pablo.vix
If you wanna read as a file, I believe there still is a similar solution:
如果您想作为文件阅读,我相信仍然有类似的解决方案:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());
回答by Juozas Kontvainis
To access a file in a jar you have two options:
要访问 jar 中的文件,您有两个选择:
Place the file in directory structure matching your package name (after extracting .jar file, it should be in the same directory as .class file), then access it using
getClass().getResourceAsStream("file.txt")
Place the file at the root (after extracting .jar file, it should be in the root), then access it using
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")
将文件放在与包名匹配的目录结构中(解压 .jar 文件后,它应该与 .class 文件在同一目录中),然后使用
getClass().getResourceAsStream("file.txt")
将文件放在根目录下(解压 .jar 文件后,它应该在根目录下),然后使用访问它
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")
The first option may not work when jar is used as a plugin.
当 jar 用作插件时,第一个选项可能不起作用。
回答by Petterson
Make sure that you work with the correct separator. I replaced all /
in a relative path with a File.separator
. This worked fine in the IDE, however did not work in the build JAR.
确保您使用正确的分隔符。我用/
一个相对路径替换了所有内容File.separator
。这在 IDE 中运行良好,但在构建 JAR 中不起作用。
回答by Sujan M.
If you are using spring, then you can use the the following method to read file from src/main/resources:
如果您使用的是 spring,那么您可以使用以下方法从 src/main/resources 读取文件:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.core.io.ClassPathResource;
public String readFileToString(String path) throws IOException {
StringBuilder resultBuilder = new StringBuilder("");
ClassPathResource resource = new ClassPathResource(path);
try (
InputStream inputStream = resource.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
resultBuilder.append(line);
}
}
return resultBuilder.toString();
}
回答by MForm
I had this problem before and I made fallback way for loading. Basically first way work within .jar file and second way works within eclipse or other IDE.
我之前遇到过这个问题,我做了后备加载方式。基本上第一种方式在 .jar 文件中工作,第二种方式在 eclipse 或其他 IDE 中工作。
public class MyClass {
public static InputStream accessFile() {
String resource = "my-file-located-in-resources.txt";
// this is the path within the jar file
InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
if (input == null) {
// this is how we load file within editor (eg eclipse)
input = MyClass.class.getClassLoader().getResourceAsStream(resource);
}
return input;
}
}
回答by Naor Bar
Up until now (December 2017), this is the only solution I found which works bothinside and outside the IDE.
到目前为止(2017 年 12 月),这是我发现的唯一在 IDE 内部和外部都有效的解决方案。
Use PathMatchingResourcePatternResolver
使用PathMatchingResourcePatternResolver
Note:it works also in spring-boot
注意:它也适用于 spring-boot
In this example I'm reading some files located in src/main/resources/my_folder:
在这个例子中,我正在读取位于src/main/resources/my_folder 中的一些文件:
try {
// Get all the files under this inner resource folder: my_folder
String scannedPackage = "my_folder/*";
PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
Resource[] resources = scanner.getResources(scannedPackage);
if (resources == null || resources.length == 0)
log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
else {
for (Resource resource : resources) {
log.info(resource.getFilename());
// Read the file content (I used BufferedReader, but there are other solutions for that):
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// ...
// ...
}
bufferedReader.close();
}
}
} catch (Exception e) {
throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}
回答by sendon1982
You can use class loader which will read from classpath as ROOT path (without "/" in the beginning)
您可以使用类加载器,它将从类路径中读取为 ROOT 路径(开头没有“/”)
InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
回答by irvifa
I think this should be works in java as well. The following code I use is using kotlin.
我认为这也应该适用于 Java。我使用的以下代码使用 kotlin。
val resource = Thread.currentThread().contextClassLoader.getResource('resources.txt')
回答by Ram C
For some reason classLoader.getResource()
always returned null when I deployed the web application to WildFly 14. getting classLoader from getClass().getClassLoader()
or Thread.currentThread().getContextClassLoader()
returns null.
出于某种原因,classLoader.getResource()
当我将 Web 应用程序部署到 WildFly 14 时,总是返回 null。从获取 classLoadergetClass().getClassLoader()
或Thread.currentThread().getContextClassLoader()
返回 null。
getClass().getClassLoader()
API doc says,
getClass().getClassLoader()
API 文档说,
"Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader."
“返回类的类加载器。某些实现可能使用 null 来表示引导类加载器。如果此类由引导类加载器加载,则此方法将在此类实现中返回 null。”
may be if you are using WildFly and yours web application try this
可能是如果您使用的是 WildFly 并且您的网络应用程序试试这个
request.getServletContext().getResource()
returned the resource url. Here request is an object of ServletRequest.
request.getServletContext().getResource()
返回资源网址。这里的 request 是 ServletRequest 的一个对象。