Java 프로젝트의 컴파일 된 JAR의 패키지 내에서 텍스트 파일을로드하고 있습니다. 관련 디렉토리 구조는 다음과 같습니다.
/src/initialization/Lifepaths.txt
내 코드는를 Class::getResourceAsStream
반환하기 위해 호출 하여 파일을로드 합니다 InputStream
.
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
인쇄물은 null
내가 무엇을 사용하든 항상 인쇄 합니다. 위의 방법이 작동하지 않는 이유를 잘 모르겠으므로 시도해 보았습니다.
"/src/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
이 둘 중 어느 것도 작동하지 않습니다. 나는 한 읽고 많은 질문을 지금까지 주제에,하지만 그들 중 누구도 도움이 없었다 – 보통, 그들은 단지 이미하고 있어요 루트 경로를 사용하여로드 파일을 말한다. 또는 현재 디렉토리에서 파일을로드 (로드 만하면됩니다 filename
). 내도 시도했습니다. 파일이 적절한 이름으로 적절한 위치에있는 JAR로 컴파일됩니다.
이 문제를 어떻게 해결합니까?
답변
Lifepaths.class.getClass().getResourceAsStream(...)
시스템 클래스 로더를 사용하여 리소스를로드하면 JAR이 표시되지 않기 때문에 분명히 실패합니다.
Lifepaths.class.getResourceAsStream(...)
Lifepaths 클래스를로드 한 것과 동일한 클래스 로더를 사용하여 자원을로드하며 JAR의 자원에 액세스해야합니다.
답변
규칙은 다음과 같습니다.
- JAR 내부에로드 할 파일의 위치를 확인하십시오 (따라서 실제로 JAR에 추가되었는지 확인하십시오)
- 절대 경로를 사용하십시오. 경로는 JAR의 루트에서 시작합니다.
- 상대 경로를 사용하십시오 : 경로는 getResource / getResoucreAsStream을 호출하는 클래스의 패키지 디렉토리에서 시작합니다
그리고 시도하십시오 :
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
대신에
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(차이가 있는지 확실하지 않지만 전자는 올바른 ClassLoader / JAR을 사용하지만 후자는 확실하지 않습니다)
답변
따라서 jar에서 리소스를 가져 오는 여러 가지 방법이 있으며 경로를 다르게 지정 해야하는 구문이 약간 다릅니다.
내가 본 가장 좋은 설명은 JavaWorld 의이 기사입니다 . 여기에 요약하지만 더 알고 싶다면 기사를 확인하십시오.
행동 양식
1) ClassLoader.getResourceAsStream()
.
형식 : “/”로 구분 된 이름; 선행 “/”없음 (모든 이름은 절대적 임)
예: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2) Class.getResourceAsStream()
형식 : “/”로 구분 된 이름; 선행 “/”는 절대 이름을 나타냅니다. 다른 모든 이름은 클래스 패키지와 관련이 있습니다.
예: this.getClass().getResourceAsStream("/some/pkg/resource.properties");
답변
절대 경로를 사용하지 말고 프로젝트의 ‘resources’디렉토리를 기준으로하십시오. ‘resources’디렉토리에서 MyTest.txt의 내용을 표시하는 빠르고 더러운 코드입니다.
@Test
public void testDefaultResource() {
// can we see default resources
BufferedInputStream result = (BufferedInputStream)
Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
byte [] b = new byte[256];
int val = 0;
String txt = null;
do {
try {
val = result.read(b);
if (val > 0) {
txt += new String(b, 0, val);
}
} catch (IOException e) {
e.printStackTrace();
}
} while (val > -1);
System.out.println(txt);
}
답변
스트림을 얻으려면 이것을 시도하십시오. 즉, 먼저 URL을 얻은 다음 스트림으로여십시오.
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
한 번 비슷한 질문이있었습니다 : jar에서 txt 파일을 읽는 데 실패하지만 이미지를 읽는 것이 좋습니다.
답변
사용중인 ClassLoader에 문제가있는 것 같습니다. contextClassLoader를 사용하여 클래스를로드하십시오. 정적 / 비 정적 방법인지 여부에 관계없이
Thread.currentThread().getContextClassLoader().getResourceAsStream
……
답변
나는 비슷한 문제에서 나 자신을 발견했다. maven을 사용하고 있기 때문에 다음과 같은 내용을 포함하도록 pom.xml을 업데이트해야했습니다.
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
해당 폴더의 위치를 지정하려면 여기에 리소스 태그를 기록하십시오. 중첩 된 프로젝트가있는 경우 (내가하는 것처럼) 작업중인 모듈이 아닌 다른 영역에서 리소스를 가져오고 싶을 수 있습니다. 유사한 구성 데이터를 사용하는 경우 각 리포지토리에서 동일한 파일을 유지하는 데 도움이됩니다.