是否有API获取类路径资源(例如,我从Class.getResource(String)
获得的内容)为java.nio.file.Path
?理想情况下,我想用类路径资源来使用新奇的Path API。类路径资源的java.nio.file.Path
回答
这一次为我的作品:
return Paths.get(ClassLoader.getSystemResource(resourceName).toURI());
这不适用于.jar文件中的资源。 – VGR
@VGR如果.jar文件中的资源可以尝试这个'\t \t \t Resource resource = new ClassPathResource(“usage.txt”); \t \t \t BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));'请参阅http://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as- jar – zhuguowei
事实证明,你可以在内置的Zip File System provider的帮助下做到这一点。但是,将资源URI直接传递给Paths.get
将不起作用;相反,必须首先创建的jar URI一个zip文件系统没有条目名称,然后参考该文件系统中的条目:
static Path resourceToPath(URL resource)
throws IOException,
URISyntaxException {
Objects.requireNonNull(resource, "Resource URL cannot be null");
URI uri = resource.toURI();
String scheme = uri.getScheme();
if (scheme.equals("file")) {
return Paths.get(uri);
}
if (!scheme.equals("jar")) {
throw new IllegalArgumentException("Cannot convert to Path: " + uri);
}
String s = uri.toString();
int separator = s.indexOf("!/");
String entryName = s.substring(separator + 2);
URI fileURI = URI.create(s.substring(0, separator));
FileSystem fs = FileSystems.newFileSystem(fileURI,
Collections.<String, Object>emptyMap());
return fs.getPath(entryName);
}
小心新创建的fs。使用同一个jar的第二个调用会抛出一个抱怨已经存在的文件系统的异常。 (FileSystem fs = ...){return fs.getPath(entryName);}或者如果你想让这个缓存做更高级的处理,会更好。目前的形式是有风险的。 – raisercostin
除了潜在的未关闭的新文件系统的问题之外,关于方案之间关系的假设以及打开新文件系统的必要性以及URI内容的迷惑限制了解决方案的实用性。我已经设置了一个[新答案](http://stackoverflow.com/a/36021165/2711488),它显示了一种简化操作的通用方法,并同时处理新的Java 9类存储等新方案。它也适用于应用程序中的其他人已经打开文件系统(或者该方法对同一个jar被调用两次)... – Holger
根据此解决方案的用法,非关闭的'newFileSystem'可能导致多个资源在打开永远。尽管@raisercostin附录在尝试创建已经创建的文件系统时避免了错误,但如果尝试使用返回的“Path”,将会得到“ClosedFileSystemException”。 @Holger响应对我来说效果很好。 –
我写了一个小助手方法从您的班级资源中读取Paths
。使用它非常方便,因为它只需要您存储资源的类的引用以及资源本身的名称。
public static Path getResourcePath(Class<?> resourceClass, String resourceName) throws URISyntaxException {
URL url = resourceClass.getResource(resourceName);
return Paths.get(url.toURI());
}
猜测你想要做的是调用Files.lines(...)对来自类路径的资源 - 可能来自jar中。
由于Oracle曲时的路径以不使的getResource如果它驻留在一个jar文件返回可用路径的路径的概念,你需要做的是这样的:
Stream<String> stream = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("/filename.txt"))).lines();
是否需要前面的“/”在你的情况下,我不知道,但在我的情况'class.getResource'需要一个斜杠,但'getSystemResourceAsStream'找不到前缀斜杠的文件。 – Adam
你如https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html中所述,需要定义文件系统以从jar文件中读取资源。我成功读取jar文件的资源与下面的代码:
Map<String, Object> env = new HashMap<>();
try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
Path path = fs.getPath("/path/myResource");
try (Stream<String> lines = Files.lines(path)) {
....
}
}
最普遍的解决方案如下:
interface IOConsumer<T> {
void accept(T t) throws IOException;
}
public static void processRessource(URI uri, IOConsumer<Path> action) throws IOException {
try {
Path p=Paths.get(uri);
action.accept(p);
}
catch(FileSystemNotFoundException ex) {
try(FileSystem fs = FileSystems.newFileSystem(
uri, Collections.<String,Object>emptyMap())) {
Path p = fs.provider().getPath(uri);
action.accept(p);
}
}
}
的主要障碍是应对两种可能,要么,具有现有我们应该使用但不关闭的文件系统(比如file
URI或即将推出的Java 9模块存储),或者必须自己打开并安全地关闭文件系统(如zip/jar文件)。
因此,上面的解决方案将实际操作封装在interface
中,处理这两种情况,之后在第二种情况下安全地关闭,并从Java 7运行到Java 9.它在打开文件系统之前探测是否已经有打开的文件系统新的,所以它也适用于应用程序的另一个组件已经为相同的zip/jar文件打开文件系统的情况。
它可以在上面提到的所有Java版本中使用,例如,到上市的包装的(在本例java.lang
)的内容作为Path
S,这样的:
processRessource(Object.class.getResource("Object.class").toURI(), new IOConsumer<Path>() {
public void accept(Path path) throws IOException {
try(DirectoryStream<Path> ds = Files.newDirectoryStream(path.getParent())) {
for(Path p: ds)
System.out.println(p);
}
}
});
在Java 8或较新的,则可以使用lambda表达式或方法的引用来表示实际的动作,例如
processRessource(Object.class.getResource("Object.class").toURI(), path -> {
try(Stream<Path> stream = Files.list(path.getParent())) {
stream.forEach(System.out::println);
}
});
也这样做。
Java 9模块系统的最终版本打破了上面的代码示例。JRE对于Object.class.getResource("Object.class")
不一致返回路径/java.base/java/lang/Object.class
,而它应该是/modules/java.base/java/lang/AbstractMethodError.class
。这可以通过在前面加上缺少/modules/
固定当父路径报告为不存在的:
processRessource(Object.class.getResource("Object.class").toURI(), path -> {
Path p = path.getParent();
if(!Files.exists(p))
p = p.resolve("/modules").resolve(p.getRoot().relativize(p));
try(Stream<Path> stream = Files.list(p)) {
stream.forEach(System.out::println);
}
});
然后,它会再次与所有版本和存储方法的工作。
您不能从jar文件内的资源创建URI。你可以简单地将其写入到临时文件,然后使用它(java8):
Path path = File.createTempFile("some", "address").toPath();
Files.copy(ClassLoader.getSystemResourceAsStream("/path/to/resource"), path, StandardCopyOption.REPLACE_EXISTING);
- 1. 资源类路径
- 2. java.io.FileNotFoundException:类路径资源
- 3. 设置类路径资源
- 4. drools DRL类路径资源
- 5. Rails资源路径
- 6. tastypie资源路径
- 7. svn资源路径
- 8. 类路径中资源的MissingResourceException
- 9. 无法获取类路径的资源
- 10. jar中的类路径资源
- 11. Spring - 类路径资源中的相对路径
- 12. 春季类路径资源中的相对路径
- 13. Spring MVC的资源路径
- 14. 资源的路径索引
- 15. CommonJS的资源路径
- 16. Xcode的路径资源
- 17. 嵌套资源的路径
- 18. 资源的url路径
- 19. 相对于类路径提取资源
- 20. 如何向类路径添加资源
- 21. 内存映射类路径资源
- 22. 春季OSGi类路径资源问题
- 23. Eclipse:在类路径上查找资源
- 24. 类路径和资源文件
- 25. mvn mybatis java.io.FileNotFoundException:类路径资源
- 26. Symfony2的资产资源路径
- 27. WPF - 默认资源路径
- 28. CMake和资源路径
- 29. 图标资源路径
- 30. REST资源路径设计
好了,走长路(双关语意),你有'Paths.get(URI)',然后'URL.toURI ()',最后一个'getResource()'返回一个'URL'。你可以将这些链接在一起。虽然没有尝试过。 – NilsH