클래스 패스 자원의 java.nio.file.Path
클래스 패스 리소스 (예 : 내가 얻는 것 Class.getResource(String)
) 를 얻는 API가 java.nio.file.Path
있습니까? 이상적으로는 클래스 경로 리소스와 함께 새롭고 멋진 Path API를 사용하고 싶습니다.
이것은 나를 위해 작동합니다 :
return Paths.get(ClassLoader.getSystemResource(resourceName).toURI());
당신이하고 싶은 일을 추측하는 것은 클래스 경로에서 오는 리소스에서 아마도 파일 내에서 Files.lines (...)를 호출하는 것입니다.
jar 파일에 상주하는 경우 getResource가 사용 가능한 경로를 리턴하지 않도록함으로써 경로가 경로 일 때의 개념을 복잡하게 만들었으므로 다음과 같이해야합니다.
Stream<String> stream = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("/filename.txt"))).lines();
가장 일반적인 해결책은 다음과 같습니다.
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 10으로 작동합니다. 새로운 파일 시스템을 열기 전에 이미 열린 파일 시스템이 있는지 여부를 조사하므로 응용 프로그램의 다른 구성 요소가 동일한 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 이상에서는 람다 식 또는 메서드 참조를 사용하여 실제 작업을 나타낼 수 있습니다.
processRessource(Object.class.getResource("Object.class").toURI(), path -> {
try(Stream<Path> stream = Files.list(path.getParent())) {
stream.forEach(System.out::println);
}
});
똑같이
Java 9 모듈 시스템의 최종 릴리스는 위의 코드 예제를 위반했습니다. JRE는 경로 /java.base/java/lang/Object.class
를 일관성없이 반환하지만 경로 는 일치 Object.class.getResource("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);
}
});
그런 다음 모든 버전 및 저장 방법으로 다시 작동합니다.
내장 된 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);
}
최신 정보:
It’s been rightly pointed out that the above code contains a resource leak, since the code opens a new FileSystem object but never closes it. The best approach is to pass a Consumer-like worker object, much like how Holger’s answer does it. Open the ZipFS FileSystem just long enough for the worker to do whatever it needs to do with the Path (as long as the worker doesn’t try to store the Path object for later use), then close the FileSystem.
I wrote a small helper method to read Paths
from your class resources. It is quite handy to use as it only needs a reference of the class you have stored your resources as well as the name of the resource itself.
public static Path getResourcePath(Class<?> resourceClass, String resourceName) throws URISyntaxException {
URL url = resourceClass.getResource(resourceName);
return Paths.get(url.toURI());
}
You can not create URI from resources inside of the jar file. You can simply write it to the temp file and then use it (java8):
Path path = File.createTempFile("some", "address").toPath();
Files.copy(ClassLoader.getSystemResourceAsStream("/path/to/resource"), path, StandardCopyOption.REPLACE_EXISTING);
Read a File from resources folder using NIO, in 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();
}
You need to define the Filesystem to read resource from jar file as mentioned in https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html. I success to read resource from jar file with below codes:
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)) {
....
}
}
참고URL : https://stackoverflow.com/questions/15713119/java-nio-file-path-for-a-classpath-resource
'development' 카테고리의 다른 글
Android 애플리케이션의 모든 버튼에 스타일을 적용하는 방법 (0) | 2020.07.04 |
---|---|
젠킨스에서 파이썬 단위 테스트? (0) | 2020.07.04 |
std :: numeric_limits를 호출하기 전에 단항 "+"의 목적은 무엇입니까? (0) | 2020.07.04 |
문자열을 어떻게 연결합니까? (0) | 2020.07.04 |
knockout.js를 ASP.NET MVC ViewModels와 함께 사용하는 방법? (0) | 2020.07.04 |