jar 내에서 리소스 파일 읽기
다음과 같이 항아리 내의 리소스를 읽습니다.
File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferedReader reader = new BufferedReader(new FileReader(file));
//Read the file
Eclipse에서 실행할 때는 정상적으로 동작합니다만, 이것을 항아리로 내보낸 후 실행하면, IlgulateArgument가 있습니다.예외:
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());
반대로 작용합니다(항아리에서는 작동하지만 일식은 작동하지 않습니다).
이클립스를 사용하고 있는데 파일이 있는 폴더가 클래스 폴더에 있습니다.
리소스를 파일로 지정하는 대신 getResourceAsStream을 통해 리소스의 InputStream을 반환하도록 ClassLoader에 요청하십시오.
try (InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
// Use resource
}
의 경우file.txt클래스 패스에서 리소스를 사용할 수 있습니다.그러면 이 접근법은 classpath의 유무에 관계없이 동일하게 동작합니다.file.txt리소스가 에 있습니다.classes/디렉토리 또는 내부jar.
그URI is not hierarchicaljar 파일 내의 리소스에 대한 URI가 다음과 같이 되어 있기 때문에 발생합니다.file:/example.jar!/file.txt. 내의 엔트리를 읽을 수 없습니다.jar(a)zip파일)이 오래된 파일인 것처럼 보이게 됩니다.
이는 다음 질문에 대한 답변으로 잘 설명됩니다.
항아리 내의 파일에 액세스 하려면 , 다음의 2개의 옵션이 있습니다.
패키지명과 일치하는 디렉토리 구조(.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 내외에서 모두 기능하는 솔루션은 이것뿐입니다.
Path Matching Resource Pattern Resolver 사용
주의: 스프링 부트에서도 동작합니다.
이 예에서는 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);
}
저 같은 경우에는 드디어 이렇게 해서
import java.lang.Thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;
final BufferedReader in = new BufferedReader(new InputStreamReader(
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt"))
); // no initial slash in file.txt
문제는 특정 서드파티 라이브러리에서 입력 스트림 대신 파일 경로 이름이 요구된다는 것입니다.대부분의 답변은 이 문제를 다루지 않습니다.
이 경우 한 가지 해결 방법은 리소스 내용을 임시 파일에 복사하는 것입니다."da" "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();
}
올바른 구분 기호로 작업해야 합니다. 것을 했다./에서 " " "를 하여"를 사용합니다.File.separatorIDE에서는 정상적으로 동작했지만 빌드 JAR에서는 동작하지 않았습니다.
나는 해결책을 찾았다.
BufferedReader br = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream(path)));
"Main"을 코드화한 Java 클래스로 바꾸고 "path"를 jar 파일 내의 경로로 바꿉니다.
예를 들어 State1을 입력합니다.com.issac.state 패키지에 txt를 입력한 다음 Linux 또는 Mac을 실행하는 경우 경로를 "/com/issac/state/State1"로 입력합니다.Windows 를 실행하고 있는 경우는, 「\com\issac\state\State1」이라고 패스를 입력합니다.파일을 찾을 수 없음 예외가 발생하지 않는 한 .txt 확장자를 파일에 추가하지 마십시오.
이 코드는 Eclipse 및 Exported Runnable JAR에서 모두 작동합니다.
private String writeResourceToFile(String resourceName) throws IOException {
File outFile = new File(certPath + File.separator + resourceName);
if (outFile.isFile())
return outFile.getAbsolutePath();
InputStream resourceStream = null;
// Java: In caso di JAR dentro il JAR applicativo
URLClassLoader urlClassLoader = (URLClassLoader)Cypher.class.getClassLoader();
URL url = urlClassLoader.findResource(resourceName);
if (url != null) {
URLConnection conn = url.openConnection();
if (conn != null) {
resourceStream = conn.getInputStream();
}
}
if (resourceStream != null) {
Files.copy(resourceStream, outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return outFile.getAbsolutePath();
} else {
System.out.println("Embedded Resource " + resourceName + " not found.");
}
return "";
}
드디어 오류를 해결했습니다.
String input_path = "resources\\file.txt";
input_path = input_path.replace("\\", "/"); // doesn't work with back slash
URL file_url = getClass().getClassLoader().getResource(input_path);
String file_path = new URI(file_url.toString().replace(" ","%20")).getSchemeSpecificPart();
InputStream file_inputStream = file_url.openStream();
클래스 경로에서 ROOT 경로로 읽을 클래스 로더를 사용할 수 있습니다(처음에는 "/"가 없음).
InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
이유에선지.classLoader.getResource() 14에 했을 때 했습니다.WildFly 14에서 classLoader를 .getClass().getClassLoader() ★★★★★★★★★★★★★★★★★」Thread.currentThread().getContextClassLoader()manager가 됩니다.
getClass().getClassLoader()API를 사용합니다.
"클래스의 클래스 로더를 반환합니다.일부 구현에서는 부트스트랩클래스 로더를 나타내기 위해 null을 사용할 수 있습니다.이 메서드는 부트스트랩 클래스 로더에 의해 이 클래스가 로드된 경우 이러한 구현에서 null을 반환합니다."
WildFly를 사용하고 있는 경우 및 웹 어플리케이션을 사용해 보십시오.
request.getServletContext().getResource()【URL】【URL】ServletRequest를 사용하다
spring을 사용하는 경우 다음 방법을 사용하여 src/main/resources에서 파일을 읽을 수 있습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.core.io.ClassPathResource;
public String readFileToString(String path) throws IOException {
StringBuilder resultBuilder = new StringBuilder("");
ClassPathResource resource = new ClassPathResource(path);
try (
InputStream inputStream = resource.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
resultBuilder.append(line);
}
}
return resultBuilder.toString();
}
다음 코드는 스프링 부트(kotlin)로 동작합니다.
val authReader = InputStreamReader(javaClass.getResourceAsStream("/file1.json"))
파일로 읽고 싶다면, 비슷한 해결책이 아직 있다고 생각합니다.
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());
언급URL : https://stackoverflow.com/questions/20389255/reading-a-resource-file-from-within-jar
'programing' 카테고리의 다른 글
| Vue는 맵 및 세트 데이터 유형에 대한 반응성을 지원합니까? (0) | 2022.07.11 |
|---|---|
| 절대 실행되지 않는 코드가 정의되지 않은 동작을 호출할 수 있습니까? (0) | 2022.07.11 |
| 구성 요소의 vuex 작업에서 상태 데이터를 반환하는 방법 (0) | 2022.07.11 |
| c/c++ 로 로그 베이스(2)를 쓰는 방법 (0) | 2022.07.11 |
| Vue.js의 vuex 스토어에서 참조되는 이미지에 링크하는 중 (0) | 2022.07.11 |