Java 리소스를 파일로


122

Java에서 클래스 로더를 통해 jar에서 검색된 리소스에 파일 인스턴스를 구성하는 방법이 있습니까?

내 응용 프로그램은 jar (기본값) 또는 런타임에 지정된 파일 시스템 디렉토리 (사용자 입력)의 일부 파일을 사용합니다.
a) 이러한 파일을 스트림으로로드
b) 사용자 정의 디렉토리 또는 jar의 디렉토리에 각각 파일을 나열 하는 일관된 방법을 찾고 있습니다.

편집 : 분명히 이상적인 접근 방식은 java.io.File에서 완전히 떨어져있는 것입니다. 클래스 경로에서 디렉토리를로드하고 그 내용 (그 안에 포함 된 파일 / 엔티티)을 나열하는 방법이 있습니까?

답변:


58

ClassLoader.getResourceAsStream그리고 Class.getResourceAsStream확실히 리소스 데이터를로드하기 위해 이동하는 방법입니다. 그러나 클래스 경로의 요소 내용을 "나열"하는 방법이 없다고 생각합니다.

어떤 경우에는 이것이 불가능할 수 있습니다. 예를 들어 는 요청한 리소스 이름에 따라 데이터를 즉석에서 생성 ClassLoader 할 수 있습니다. 당신이 보면 ClassLoader(클래스 패스 메커니즘을 통해 작동하는 무슨이 기본적으로있는) API 당신은 당신이 원하는 것을 무엇이든이없는 볼 수 있습니다.

실제로 jar 파일이 있다는 것을 알고 있다면 사용 가능한 파일 ZipInputStream을 찾기 위해이를 로드 할 수 있습니다. 그래도 디렉토리와 jar 파일에 대해 다른 코드가 있음을 의미합니다.

파일이 먼저 별도로 생성되는 경우 한 가지 대안은 사용 가능한 리소스 목록이 포함 된 일종의 매니페스트 파일을 포함하는 것입니다. jar 파일에 번들로 묶거나 파일 시스템에 파일로 포함하고 사용자에게 리소스 선택을 제공하기 전에로드합니다.


3
성가신 일이라는 데 동의하지만 ClassLoader를 다른 방식으로 더 널리 적용 할 수 있습니다. 예를 들어, 웹은 파일을 가져 오는 데 적합하지만 일반적으로 파일을 나열 하지 않기 때문에 "웹 클래스 로더"를 작성하기 쉽습니다 .
Jon Skeet

그것은 것 같은 당신이 부하하려고하는 자원이 1MiB보다 훨씬 더 큰 경우 InputStream당신이에서 얻을 getResourceAsStream그 크기 후 자원의 바이트를 검색하기 위해 정지하고이 항아리와 같은 압축 파일 시스템에 포함되어 IFF에 대신 0을 반환합니다. getResource이 경우에 파일을 독립적 으로 사용 하고로드 해야하는 것 같습니다 .
mgttlinger

1
@mgttlinger : 그럴 것 같지 않습니다. 가능하다면 재현과 함께 새 질문을 게시 할 가치가있을 것입니다.
Jon Skeet

이 문제는 read읽을 데이터의 양을 결정하는 방법 때문이었습니다 (나는 몰랐습니다). 그리고 읽는 파일이 일반 폴더에 있으면 전체 파일을 읽은 것 같습니다. 파일이 패키지 되었기 때문에 jar 안에있는 경우 파일의 일부만 읽습니다.
mgttlinger

1
@mgttlinger : 아니요, 일부만 읽을 수는 없지만 모든 읽기 호출에서 제공되는 전체 버퍼를 채우지는 않을 수 있습니다. 항상 그렇듯이 InputStream전체 리소스를 읽으려면 read-1을 반환 할 때까지 반복해야 합니다.
Jon Skeet

98

나는 같은 문제가 있었고 다음을 사용할 수있었습니다.

// Load the directory as a resource
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()

45
이 접근 방식은 클래스 경로의 JAR에서는 작동하지 않으며 파일 및 디렉토리에서만 작동합니다
yegor256

1
@ yegor256 파일이 항아리에있는 경우 FileSystem개체를 만들고 그 Path에서 가져올 수 있습니다 . 그러면 평소처럼 읽을 수 있습니다. ( stackoverflow.com/a/22605905/1876344 참조 )
mgttlinger 2015 년

53

다음은 내 응용 프로그램 중 하나의 코드입니다. 필요에 맞는지 알려주세요. 사용하려는 파일을 알고있는 경우 사용할 수 있습니다.

URL defaultImage = ClassA.class.getResource("/packageA/subPackage/image-name.png");
File imageFile = new File(defaultImage.toURI());

도움이되기를 바랍니다.


그렇습니다 toURI(). 그러나 실패 할 것입니다.
Olivier Faucheux

10

jar에서 검색된 리소스에서 File 인스턴스를 구성하는 신뢰할 수있는 방법은 리소스를 스트림으로 임시 파일에 복사하는 것입니다 (JVM이 종료되면 임시 파일이 삭제됨).

public static File getResourceAsFile(String resourcePath) {
    try {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
        if (in == null) {
            return null;
        }

        File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        tempFile.deleteOnExit();

        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            //copy stream
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

4

이 시도:

ClassLoader.getResourceAsStream ("some/pkg/resource.properties");

더 많은 방법을 사용할 수 있습니다. 예를 들어 다음을 참조하십시오. http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html


응답 해 주셔서 감사합니다. getResourceAsStream에 대해 알고 있지만이를 통해 클래스 경로에서 디렉토리를로드 할 수 없다고 생각합니다.
Mantrum

Java 디렉토리에는 파일 (UNIX 루트)이 있으므로 적어도 시도해야합니다.
topchef

java.io.File을 사용해야 할 디렉토리에 파일을 나열하려고 생각합니다. File에 전달할 수있는 URL을 반환하는 ClassLoader.findResource를 사용하여 파일을 조회 할 수 있습니다.
Nathan Voxland

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.