Pri*_*CJC 207 java resources jar file embedded-resource
我想从我的jar中读取资源,如下所示:
File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));
//Read the file
Run Code Online (Sandbox Code Playgroud)
并且它在Eclipse中运行时工作正常,但是如果我将它导出到jar中运行它就会出现IllegalArgumentException:
Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical
Run Code Online (Sandbox Code Playgroud)
而且我真的不知道为什么,但经过一些测试我发现如果我改变了
file = new File(getClass().getResource("/file.txt").toURI());
Run Code Online (Sandbox Code Playgroud)
至
file = new File(getClass().getResource("/folder/file.txt").toURI());
Run Code Online (Sandbox Code Playgroud)
然后它的工作正好相反(它适用于jar而不是eclipse).
我正在使用Eclipse,我的文件夹在一个类文件夹中.
Dre*_*nis 348
而不是尝试将资源作为文件来处理,而只是要求ClassLoader通过getResourceAsStream返回资源的InputStream:
InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
Run Code Online (Sandbox Code Playgroud)
只要file.txt资源在类路径上可用,那么无论file.txt资源是在classes/目录中还是在内部,这种方法都将以相同的方式工作jar.
之所以URI is not hierarchical发生这种情况,是因为jar文件中资源的URI看起来像这样:file:/example.jar!/file.txt.您无法读取jar(zip文件)中的条目,就像它是一个普通的旧文件.
这可以通过以下答案得到很好的解释:
Juo*_*nis 18
要访问jar中的文件,您有两个选择:
将文件放在与包名匹配的目录结构中(在解压缩.jar文件后,它应该与.class文件位于同一目录中),然后使用 getClass().getResourceAsStream("file.txt")
将文件放在根目录下(在解压缩.jar文件后,它应该在根目录中),然后使用它来访问它 Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")
当jar用作插件时,第一个选项可能不起作用.
小智 9
我之前遇到过这个问题,我做了后备加载方式。基本上第一种方式在 .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;
}
}
Run Code Online (Sandbox Code Playgroud)
问题是某些第三方库需要文件路径名而不是输入流。大多数答案都没有解决这个问题。
在这种情况下,一种解决方法是将资源内容复制到临时文件中。以下示例使用 jUnit 的TemporaryFolder.
private List<String> decomposePath(String path){
List<String> reversed = Lists.newArrayList();
File currFile = new File(path);
while(currFile != null){
reversed.add(currFile.getName());
currFile = currFile.getParentFile();
}
return Lists.reverse(reversed);
}
private String writeResourceToFile(String resourceName) throws IOException {
ClassLoader loader = getClass().getClassLoader();
InputStream configStream = loader.getResourceAsStream(resourceName);
List<String> pathComponents = decomposePath(resourceName);
folder.newFolder(pathComponents.subList(0, pathComponents.size() - 1).toArray(new String[0]));
File tmpFile = folder.newFile(resourceName);
Files.copy(configStream, tmpFile.toPath(), REPLACE_EXISTING);
return tmpFile.getAbsolutePath();
}
Run Code Online (Sandbox Code Playgroud)
到目前为止(2017 年 12 月),这是我发现的唯一在 IDE 内部和外部都有效的解决方案。
使用PathMatchingResourcePatternResolver
注意:它也适用于 spring-boot
在这个例子中,我正在读取位于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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
275571 次 |
| 最近记录: |