항아리 내에서 다음과 같이 리소스를 읽고 싶습니다.
File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));
//Read the file
Eclipse에서 실행할 때 정상적으로 작동하지만 항아리로 내 보내면 IllegalArgumentException이 발생합니다.
Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical
왜 그런지 모르겠지만 테스트를 통해 변경하면 발견했습니다.
file = new File(getClass().getResource("/file.txt").toURI());
에
file = new File(getClass().getResource("/folder/file.txt").toURI());
그런 다음 반대의 방식으로 작동합니다 (jar에서는 작동하지만 일식에서는 작동하지 않습니다).
Eclipse를 사용하고 있으며 파일이있는 폴더가 클래스 폴더에 있습니다.
답변
리소스를 파일 로 지정하려고하지 않고 클래스 로더 에게 getResourceAsStream 을 통해 대신 리소스에 대한 InputStream 을 반환 하도록 요청하십시오 .
InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
만큼 file.txt
자원이 클래스 경로에 볼 수 있습니다 다음이 접근 방식에 관계없이 여부와 같은 방식으로 작동합니다 file.txt
리소스가있는 classes/
디렉토리 또는 내부 jar
.
은 URI is not hierarchical
jar 파일 내의 리소스에 대한 URI는 다음과 같이 뭔가에 가고 있기 때문에 발생합니다 file:/example.jar!/file.txt
. 평범한 오래된 File 과 같이 jar
( zip
파일) 내의 항목을 읽을 수 없습니다 .
이것은 다음에 대한 답변으로 잘 설명됩니다.
답변
jar 파일에 액세스하려면 두 가지 옵션이 있습니다.
-
패키지 이름과 일치하는 디렉토리 구조에 파일을 배치하고 (.jar 파일을 추출한 후 .class 파일과 동일한 디렉토리에 있어야 함) 다음을 사용하여 액세스하십시오.
getClass().getResourceAsStream("file.txt")
-
파일을 루트에 놓고 (.jar 파일을 추출한 후 루트에 있어야 함) 다음을 사용하여 액세스하십시오.
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")
jar을 플러그인으로 사용하는 경우 첫 번째 옵션이 작동하지 않을 수 있습니다.
답변
나는이 문제가 전에 있었고 로딩을위한 대체 방법을 만들었다. 기본적으로 첫 번째 방법은 .jar 파일 내에서 작동하고 두 번째 방법은 일식 또는 다른 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;
}
}
답변
지금까지 (2017 년 12 월), 이것이 IDE 내부와 외부에서 모두 작동하는 유일한 솔루션 입니다.
PathMatchingResourcePatternResolver 사용
참고 : 스프링 부트에서도 작동합니다 .
이 예제에서는 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);
}
답변
문제는 특정 타사 라이브러리에 입력 스트림이 아닌 파일 경로 이름이 필요하다는 것입니다. 대부분의 답변은이 문제를 해결하지 못합니다.
이 경우 한 가지 해결 방법은 리소스 내용을 임시 파일로 복사하는 것입니다. 다음 예제는 jUnit ‘s를 사용합니다 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();
}
답변
파일로 읽으려면 여전히 비슷한 해결책이 있다고 생각합니다.
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());
답변
올바른 구분 기호로 작업해야합니다. /
상대 경로의 모든 것을로 대체 했습니다 File.separator
. 이것은 IDE에서 잘 작동했지만 빌드 JAR에서는 작동하지 않았습니다.