[java] jar 파일 내부에서 “폴더”리소스를 얻으려면 어떻게해야합니까?

프로젝트 루트에 리소스 폴더 / 패키지를 가지고 있는데 특정 파일을로드하고 싶지 않습니다. 특정 파일을로드하려면 class.getResourceAsStream을 사용하고 괜찮습니다! 내가 실제로하고 싶은 것은 resources 폴더 내에 “Folder”를로드하고 해당 폴더 안의 파일을 반복하여 각 파일에 스트림을 가져 와서 내용을 읽는 것입니다 … 런타임 전에 파일 이름이 결정되지 않는다고 가정하십시오. … 어떻게해야합니까? jar 파일의 폴더 안에있는 파일 목록을 얻는 방법이 있습니까? 리소스가있는 Jar 파일은 코드가 실행되는 것과 동일한 jar 파일입니다.

미리 감사드립니다 …



답변

마지막으로 해결책을 찾았습니다.

final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

if(jarFile.isFile()) {  // Run with JAR file
    final JarFile jar = new JarFile(jarFile);
    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
    while(entries.hasMoreElements()) {
        final String name = entries.nextElement().getName();
        if (name.startsWith(path + "/")) { //filter according to the path
            System.out.println(name);
        }
    }
    jar.close();
} else { // Run with IDE
    final URL url = Launcher.class.getResource("/" + path);
    if (url != null) {
        try {
            final File apps = new File(url.toURI());
            for (File app : apps.listFiles()) {
                System.out.println(app);
            }
        } catch (URISyntaxException ex) {
            // never happens
        }
    }
}

두 번째 블록은 jar 파일이 아닌 IDE에서 응용 프로그램을 실행할 때 작동합니다. 좋지 않으면 제거 할 수 있습니다.


답변

다음을 시도하십시오. 클래스 경로가 com.abc.package.MyClass이고
리소스 "<PathRelativeToThisClassFile>/<ResourceDirectory>"파일이 src / com / abc / package / resources / 내에있는 경우 리소스 경로를 확인하십시오 .

URL url = MyClass.class.getResource("resources/");
if (url == null) {
     // error - missing folder
} else {
    File dir = new File(url.toURI());
    for (File nextFile : dir.listFiles()) {
        // Do something with nextFile
    }
}

당신은 또한 사용할 수 있습니다

URL url = MyClass.class.getResource("/com/abc/package/resources/");


답변

나는 이것이 몇 년 전에 알고 있습니다. 그러나 다른 사람들에게만이 주제가 있습니다. 당신이 할 수있는 일은 getResourceAsStream()디렉토리 경로와 함께 메소드 를 사용 하는 것이며 입력 스트림은 해당 디렉토리의 모든 파일 이름을 갖습니다. 그런 다음 각 파일 이름으로 dir 경로를 연결하고 루프에서 각 파일에 대해 getResourceAsStream을 호출 할 수 있습니다.


답변

jar에 포장 된 리소스에서 일부 hadoop 구성을로드하려고 시도하는 동안 IDE와 jar (릴리스 버전)에서 동일한 문제가 발생했습니다.

java.nio.file.DirectoryStream로컬 파일 시스템과 jar 모두에서 디렉토리 내용을 반복하는 것이 가장 효과적이라는 것을 알았 습니다.

String fooFolder = "/foo/folder";
....

ClassLoader classLoader = foofClass.class.getClassLoader();
try {
    uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
    throw new FooException(e.getMessage());
} catch (NullPointerException e){
    throw new FooException(e.getMessage());
}

if(uri == null){
    throw new FooException("something is wrong directory or files missing");
}

/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
    /** jar case */
    try{
        URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
        //jar.toString() begins with file:
        //i want to trim it out...
        Path jarFile = Paths.get(jar.toString().substring("file:".length()));
        FileSystem fs = FileSystems.newFileSystem(jarFile, null);
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
        for(Path p: directoryStream){
            InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
        performFooOverInputStream(is);
        /** your logic here **/
            }
    }catch(IOException e) {
        throw new FooException(e.getMessage());
    }
}
else{
    /** IDE case */
    Path path = Paths.get(uri);
    try {
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
        for(Path p : directoryStream){
            InputStream is = new FileInputStream(p.toFile());
            performFooOverInputStream(is);
        }
    } catch (IOException _e) {
        throw new FooException(_e.getMessage());
    }
}


답변

다음 코드는 원하는 “폴더”를 항아리 안에 있는지 여부에 관계없이 Path로 반환합니다.

  private Path getFolderPath() throws URISyntaxException, IOException {
    URI uri = getClass().getClassLoader().getResource("folder").toURI();
    if ("jar".equals(uri.getScheme())) {
      FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
      return fileSystem.getPath("path/to/folder/inside/jar");
    } else {
      return Paths.get(uri);
    }
  }

Java 7 이상이 필요합니다.


답변

또 다른 솔루션은 다음 ResourceLoader과 같이 사용할 수 있습니다 .

import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;

@Autowire
private ResourceLoader resourceLoader;

...

Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
    load(fi.next())
}


답변

단순 … OSGi를 사용하십시오. OSGi에서 findEntries 및 findPaths를 사용하여 번들 항목을 반복 할 수 있습니다.