programing

getResourceAsStream이 null을 반환합니다.

copyandpastes 2022. 7. 2. 21:29
반응형

getResourceAsStream이 null을 반환합니다.

자바 프로젝트의 컴파일된 JAR 패키지 내에서 텍스트 파일을 로드하고 있습니다.관련 디렉토리 구조는 다음과 같습니다.

/src/initialization/Lifepaths.txt

를 반환하기 위해 를 호출하여 파일을 로드합니다.

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(...) 클래스를 로드합니다.는 분명히 되지 않기 에 실패합니다.

Lifepaths.class.getResourceAsStream(...)를 로드한 의 리소스에 액세스할 수 합니다.

규칙은 다음과 같습니다.

  1. JAR 내에 로드하는 파일의 위치를 확인합니다(따라서 실제로 JAR에 추가되었는지도 확인합니다).
  2. 절대 경로 중 하나를 사용합니다.경로는 JAR의 루트에서 시작됩니다.
  3. 상대 경로 사용: getResource/getResoucreAsStream을 호출하는 클래스의 패키지 디렉토리에서 경로가 시작됩니다.

시험해 보세요.

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

대신

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(차이가 있을지는 모르겠지만, 전자는 올바른 ClassLoader/JAR을 사용합니다만, 후자는 잘 모르겠습니다.)

따라서 jar에서 리소스를 가져오는 방법은 여러 가지가 있으며 경로를 다르게 지정해야 하는 구문마다 조금씩 다릅니다.

제가 본 최고의 설명은 InfoWorld의 이 기사입니다.여기에 요약해 드리겠습니다만, 더 알고 싶으시면 기사를 확인해 보시기 바랍니다.

방법들

  1. ClassLoader.getResourceAsStream().

형식: "/" 구분된 이름, 선행 "/" 없음(모든 이름은 절대임).

::this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

  1. Class.getResourceAsStream()

형식: "/" 구분된 이름, 선행 "/"는 절대 이름을 나타냅니다. 다른 모든 이름은 클래스의 패키지에 상대적입니다.

::this.getClass().getResourceAsStream("/some/pkg/resource.properties");

2020년 9월 갱신 : 기사 링크 변경.원래 기사는 Javawolld에서 제공되었으며, 현재는 InfoWorld에서 호스팅되고 있습니다(그리고 더 많은 광고가 있습니다).

절대 경로를 사용하지 말고 프로젝트의 '리소스' 디렉터리에 상대 경로를 지정하십시오.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(); 

이전에 비슷한 질문을 한 적이 있습니다: txt 파일을 jar에서 읽는 것은 실패하지만 이미지를 읽는 것은 동작합니다.

나도 비슷한 문제에 처했다.maven을 사용하고 있기 때문에 다음과 같이 pom.xml을 업데이트해야 했습니다.

   ...
</dependencies>
<build>
    <resources>
        <resource>
            <directory>/src/main/resources</directory>
        </resource>
        <resource>
            <directory>../src/main/resources</directory>
        </resource>
    </resources>
    <pluginManagement>
        ...

폴더 위치를 지정하려면 리소스 태그를 기록해 두십시오.(저처럼) 중첩된 프로젝트가 있는 경우 작업 중인 모듈뿐만 아니라 다른 영역에서도 리소스를 얻을 수 있습니다.이것에 의해, 같은 설정 데이터를 사용하고 있는 경우, 각 레포에 같은 파일을 보관 유지하는 것을 줄일 수 있습니다.

사용하고 있는 ClassLoader에 문제가 있는 것 같습니다.contextClassLoader를 사용하여 클래스를 로드합니다.이는 정적/비정적 방식인지 여부에 관계없이

Thread.currentThread().getContextClassLoader().getResourceAsStream......

대략적으로 말하면:

getClass().getResource("/")~=Thread.currentThread().getContextClassLoader().getResource(".")

프로젝트 구조가 다음과 같다고 가정합니다.

├── src
│   ├── main
│   └── test
│       ├── java
│       │   └── com
│       │       └── github
│       │           └── xyz
│       │               └── proj
│       │                   ├── MainTest.java
│       │                   └── TestBase.java
│       └── resources
│           └── abcd.txt
└── target
    └── test-classes  <-- this.getClass.getResource("/")
        │              `--Thread.currentThread().getContextClassLoader().getResources(".")
        ├── com
        │   └── github
        │       └── xyz
        │           └── proj  <-- this.getClass.getResource(".")
        │               ├── MainTest.class
        │               └── TestBase.class
        └── resources
            └── abcd.txt

// in MainTest.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") ->  null

는 부모 를 먼저합니다.「 JVM 」 。deletegate-parent-classloader.

Lifepaths.class.getClass()는 " " " 입니다bootstrap classloader, (그래서)getResourceAsStreamJAVA_를 합니다.JAVA_AKAKE_AKAKE_AKEADA.한 "HOME"에 HOME만classpath「」, 「」.txt는 txtxt의 경우

Lifepaths.class는 " " " 입니다system classpath classloader, (그래서)getResourceAsStream는, 유저 정의의 「」를 합니다.classpath있다txt는 txtxt의 경우

「」를 사용하고 java.lang.Class#getResourceAsStream(String name), '/'로 시작하지 않는 이름은 다음과 같이 추가됩니다.package name접두사로 사용합니다. 위해서, 「」를 사용합니다.java.lang.ClassLoader#getResourceAsStream★★★★★★ 。

예를 들어 다음과 같습니다.

ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName); 

가 있었던 은, 「아까의 파일」하는 것이었습니다.My Project/Java Resources/src에 런음음음 and를 사용하다

this.getClass().getClassLoader().getResourceAsStream("myfile.txt");

으로 추가할이 파일을 패스에 합니다)./src

도움이 될지는 모르겠지만, 제 경우 /src/ 폴더에 리소스가 있어서 이 오류가 발생하고 있습니다.그런 다음 사진을 휴지통 폴더로 옮겼더니 문제가 해결되었습니다.

리소스 디렉토리(예: "src")가 클래스 경로에 있는지 확인합니다(이클립스 시 빌드 경로의 원본 디렉토리인지 확인하십시오).

클래즈가 메인 클래스 로더에서 로딩되는지 확인합니다.

다음으로 src/initialization/Lifepaths를 로드합니다.txt, 사용

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

★★★★★★★★★★★★★★★★*clazz.getResourcesAsStream(foo)clazz의 클래스 패스 내에서 clazz가 살고 있는 디렉토리를 기준으로 foo를 올려다본다.선두의 "/"는 clazz 클래스 패스의 임의의 디렉토리의 루트에서 로드됩니다.

Tomcat과 같은 컨테이너에 있거나 ClassLoaders를 사용하여 직접 작업을 수행하는 경우가 아니라면 이클립스/명령줄 클래스 경로를 유일한 클래스 로더 클래스 경로로 취급할 수 있습니다.

Maven을 사용하고 있는 경우는, 포장이 「pom」이 아니고 「jar」인 것을 확인해 주세요.

<packaging>jar</packaging>

파일에는 완전한 절대 classPath가 필요합니다.따라서 추측하는 대신 ROOT를 찾아 파일을 더 좋은 위치 기반 파일 구조인 <.war>로 이동합니다.

URL test1 = getClass().getResource("/");
URL test2 = getClass().getClassLoader().getResource("/");            
URL test3 = getClass().getClassLoader().getResource("../");

logger.info(test1.getPath()); 
logger.info(test2.getPath());
logger.info(test3.getPath());

나에게 효과가 있었던 것은 그 파일을

src/main/java/myfile.log

그리고.

InputStream is = getClass().getClassLoader().getResourceAsStream("myfile.log");
        
        if (is == null) {
            throw new FileNotFoundException("Log file not provided");
        }

jdk >=9 需要在module-info模块中把非根目录/非共父目录的包给它open了。

jdk > =9 에서는 다음과 같은 module-info.dir에서 리소스 dir를 열어야 합니다.

  • src
    • 자바
    • 자원
      • 컨피던스
        • config.json
      • log4j2.xml
      • openapi.야무지다

read conf/config.json이 필요한 경우 다음 두 가지 절차가 필요합니다.

// in module-info.java
module your.mod.name {
    open conf;
}

// then in java code
getClassLoader().getResourceAsStream("conf/config.json");

그렇지 않으면 root에서 다른 것을 읽어야 할 경우 다음과 같습니다.

getClassLoader().getResourceAsStream("openapi.yaml");

{@link java.http}가 표시됩니다.ClassLoader#getResourceAsStream(String)}이(가) 이유를 알고 있습니다.

삭제해 주세요

../src/main/resources

또는 읽으려고 하는 파일을 포함합니다.

pom.xml에서 ../src/main/resources를 관리 또는 삭제합니다.

발신자 클래스가 있었습니다.src/main/...

리소스 로딩에 도움이 된 것은 무엇입니까?src/test/resources/folder/file.properties

`properties.load(getClass().getClassLoader().getResourceAsStream("folder/file.properties"));`

https://howtodoinjava.com/java/io/read-file-from-resources-folder/

자바 11

답변은 아니지만 스크린샷을 삽입할 수 있도록 답변으로 제안합니다.

Windows 플랫폼에서 개발하시는 분들은 Microsoft 유틸리티 ProcMon, 즉 프로세스 모니터를 적극 추천합니다.

프로세스 모니터는 Microsoft가 제공하는 유틸리티 스위트의 유틸리티 중 하나입니다(다운로드하기 위해 서명할 필요도 없습니다).Microsoft가 인수하여 보관하고 있는 원래 호스트인 sysinternals.com에서 모두 구할 수 있습니다.

프로세스 모니터는 실행 중인 프로세스와 관련된 많은 이벤트를 모니터링할 수 있습니다.파일 열기 이벤트를 지정하고 파일 이름(또는 파일 이름의 일부)을 지정하면 파일 열기를 시도한 프로세스가 기록되고 검색된 모든 디렉토리가 표시됩니다.이 기능은 실행 중인 코드가 소스/구성에서 지정한 파일을 찾는 위치를 모를 때 유용합니다.다음은 예를 제시하겠습니다.

여기에 이미지 설명 입력

여기서는 스키마 파일(XSD)을 찾고 있습니다(찾지 않음).코드가 이를 사용하여 사용자가 제공한 XML을 검증할 수 있습니다.

IDEA를 사용하는 경우 IDE에서 경로를 올바르게 인식할 수 있도록 리소스 폴더를 '리소스'로 표시해야 합니다.

'book'이라는 이름의 파일이 있다고 가정해 보겠습니다.'json'은 'json/'에 있고, 그 안에 있는 리소스를 사용하려면 이렇게 하면 됩니다.

InputStream input = Main.class.getResourceAsStream("/book.json");

여기에 이미지 설명 입력

@EMRACool...대안을 제시하겠습니다.file.*.txt 파일을 것에.하는 FileInputStream() 이 귀찮은 일보다getClass().getClassLoader().getResourceAsStream() ★★★★★★★★★★★★★★★★★」getClass().getResourceAsStream()이치노

언급URL : https://stackoverflow.com/questions/16570523/getresourceasstream-returns-null

반응형