是否有一种API可以获取类路径资源(例如,我从Class.getResource(String)
中获取的内容)作为java.nio.file.Path
?理想情况下,我希望使用带有类路径资源的最新的Path
API。
是否有一种API可以获取类路径资源(例如,我从Class.getResource(String)
中获取的内容)作为java.nio.file.Path
?理想情况下,我希望使用带有类路径资源的最新的Path
API。
这个对我有效:
return Path.of(ClassLoader.getSystemResource(resourceName).toURI());
Resource resource = new ClassPathResource("usage.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
更多信息请查看 https://dev59.com/GF8e5IYBdhLWcg3wTJGL - zhuguoweiThread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
。 - ThrawnCA我猜你想做的是,在类路径下调用Files.lines(...)
方法,可能来自于一个jar包中的资源。
因为Oracle混淆了什么时候Path
是Path
,没有让getResource
方法返回可用的路径,如果它存在于jar文件中,所以你需要像这样做:
Stream<String> stream = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("/filename.txt"))).lines();
class.getResource
需要斜杠,而 getSystemResourceAsStream
在加上斜杠前找不到文件。 - Adaminterface 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文件)。java.lang
)的内容作为Path
: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模块系统的最终版本已经破坏了上述代码示例。从Java 9到12版本,Paths.get(Object.class.getResource("Object.class"))
不一致地返回路径/java.base/java/lang/Object.class
,而应该是/modules/java.base/java/lang/Object.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);
}
});
然后,它将再次与所有版本和存储方法一起工作。从JDK 13开始,这种解决方法不再必要。
原来可以通过内置的Zip文件系统提供程序来完成此操作。 但是,直接将资源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);
}
更新:
正如指出的那样,上面的代码存在资源泄漏问题,因为代码打开了一个新的FileSystem对象但从未关闭。最好的方法是传递类似于Consumer的worker对象,就像Holger的答案中所做的那样。仅在工作器需要执行与路径相关的任务时打开ZipFS FileSystem(只要工作器不尝试存储Path对象以供以后使用),然后关闭FileSystem。
newFileSystem
可能会导致多个资源一直处于打开状态。尽管@raisercostin的补充避免了在尝试创建已创建的文件系统时出现错误,但如果您尝试使用返回的Path
,则会收到ClosedFileSystemException
。 @Holger的回答对我很有效。 - José AndiasPath
对象在关闭 FileSystem
后也很难使用,因此根据代码结构的不同,它可能会变得非常丑陋。例如,您无法在实用程序方法中返回 Path
并在实用程序方法内部关闭 FileSystem
,因为使用 Path
对象将会由于底层的 FileSystem
被关闭而抛出错误。 - dutoitnsFiles#isRegularFile(Path)
不会对Jar文件中的资源返回true
。 - dutoitns我写了一个小的辅助方法来读取你的类资源中的Paths
。它非常方便易用,只需要引用你存储资源的类以及资源本身的名称。
public static Path getResourcePath(Class<?> resourceClass, String resourceName) throws URISyntaxException {
URL url = resourceClass.getResource(resourceName);
return Paths.get(url.toURI());
}
你无法从jar文件内部的资源创建URI。你可以将其简单地写入临时文件,然后使用它(java8):
Path path = File.createTempFile("some", "address").toPath();
Files.copy(ClassLoader.getSystemResourceAsStream("/path/to/resource"), path, StandardCopyOption.REPLACE_EXISTING);
使用NIO在Java8中从资源文件夹读取文件
public static String read(String fileName) {
Path path;
StringBuilder data = new StringBuilder();
Stream<String> lines = null;
try {
path = Paths.get(Thread.currentThread().getContextClassLoader().getResource(fileName).toURI());
lines = Files.lines(path);
} catch (URISyntaxException | IOException e) {
logger.error("Error in reading propertied file " + e);
throw new RuntimeException(e);
}
lines.forEach(line -> data.append(line));
lines.close();
return data.toString();
}
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)) {
....
}
}
Paths.get(URI)
гҖҒ然еҗҺжҳҜВҙURL.toURI()пјҢжңҖеҗҺжҳҜиҝ”еӣһдёҖдёӘ
URLзҡ„
getResource()`гҖӮдҪ еҸҜиғҪеҸҜд»Ҙе°Ҷе®ғ们й“ҫжҺҘеңЁдёҖиө·дҪҝз”ЁпјҢдҪҶжҲ‘жІЎжңүе°қиҜ•иҝҮгҖӮ - NilsH