programing

내 jar File에서 리소스 폴더의 폴더에 액세스하는 방법

prostudy 2022. 5. 4. 21:31
반응형

내 jar File에서 리소스 폴더의 폴더에 액세스하는 방법

프로젝트의 루트에 리소스 폴더/패키지가 있으며 특정 파일을 로드하지 않으려는 경우특정 파일을 로드하려면 class.getResourceAsStream을 사용하고 나는 괜찮을 것이다!!내가 실제로 하고 싶은 것은 자원 폴더 안에 "폴더"를 로드하고, 그 폴더 안에 있는 파일들을 반복해서 각 파일에 스트림을 가져와 내용에서 읽는 것이다.런타임 전에 파일 이름이 결정되지 않았다고 가정하십시오...어떻게 해야 하나?당신의 jar File에 있는 Folder에 있는 파일 목록을 얻을 수 있는 방법이 있는가?리소스가 있는 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
        }
    }
}

두 번째 블록은 (항아리 파일이 아닌) IDE에서 응용 프로그램을 실행할 때에만 작동하며, 마음에 들지 않으면 제거할 수 있다.

다음을 시도해 보십시오.
리소스 경로 만들기"<PathRelativeToThisClassFile>/<ResourceDirectory>"예: 클래스 경로가 com.abc.package인 경우.MyClass 및 리소스 파일은 src/com/abc/package/resource/:

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의 모든 파일 이름을 가지는 방법.그런 다음 dir 경로를 각 파일 이름으로 연결하고 루프에 있는 각 파일에 대해 getResourceAsStream을 호출하십시오.

항아리에 들어 있는 리소스에서 하둡 구성을 로드하는 동안에도 동일한 문제가 발생했었습니다...IDE 및 병(해제 버전)에 모두 적용.

찾았다java.nio.file.DirectoryStream로컬 파일 시스템과 병 모두에 대해 디렉터리 내용을 반복하는 데 최선을 다하십시오.

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);
    }
  }

자바 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())
}

다른 답들이 지적하듯이 일단 자원이 항아리 파일 안에 들어가면 상황은 정말 추악해진다.우리의 경우, 이 해결책은 다음과 같다.

https://stackoverflow.com/a/13227570/516188

테스트에서는 매우 잘 작동하지만(테스트 실행 시 코드는 jar 파일로 포장되지 않기 때문에), 앱이 실제로 정상적으로 실행될 때는 작동하지 않는다.그래서 내가 한 일은...앱에 있는 파일 리스트를 하드코드로 작성하지만, 디스크에서 실제 리스트를 읽어내는 테스트(테스트에서 작동하기 때문에 할 수 있음)가 있는데, 실제 리스트가 앱이 반환하는 리스트와 일치하지 않으면 실패한다.

그래야 내 앱에 간단한 코드( 트릭)가 있고, 시험 덕분에 목록에 새 항목을 추가하는 것을 잊지 않았을 것이다.

아래 코드는 사용자 정의 리소스 디렉터리에서 .yaml 파일을 가져온다.

ClassLoader classLoader = this.getClass().getClassLoader();
            URI uri = classLoader.getResource(directoryPath).toURI();
    
            if("jar".equalsIgnoreCase(uri.getScheme())){
                Pattern pattern = Pattern.compile("^.+" +"/classes/" + directoryPath + "/.+.yaml$");
                log.debug("pattern {} ", pattern.pattern());
                ApplicationHome home = new ApplicationHome(SomeApplication.class);
                JarFile file = new JarFile(home.getSource());
                Enumeration<JarEntry>  jarEntries = file.entries() ;
                while(jarEntries.hasMoreElements()){
                    JarEntry entry = jarEntries.nextElement();
                    Matcher matcher = pattern.matcher(entry.getName());
                    if(matcher.find()){
                        InputStream in =
                                file.getInputStream(entry);
                        //work on the stream
    
    
                    }
                }
    
            }else{
                //When Spring boot application executed through Non-Jar strategy like through IDE or as a War.
    
                String path = uri.getPath();
                File[] files = new File(path).listFiles();
               
                for(File file: files){
                    if(file != null){
                        try {
                            InputStream is = new FileInputStream(file);
                           //work on stream
                            
                        } catch (Exception e) {
                            log.error("Exception while parsing file yaml file {} : {} " , file.getAbsolutePath(), e.getMessage());
                        }
                    }else{
                        log.warn("File Object is null while parsing yaml file");
                    }
                }
            }
             

만약 당신이 Spring을 사용하고 있다면 당신은 사용할 수 있다.org.springframework.core.io.support.PathMatchingResourcePatternResolver그리고 처리하다Resource파일보다는 객체.이것은 Jar 파일 안과 밖에서 실행할 때 작동한다.

PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");

그런 다음 다음을 사용하여 데이터에 액세스할 수 있다.getInputStream및 의 파일 이름getFilename.

다음 항목을 사용하려고 해도 실패한다는 점에 유의하십시오.getFile항아리에서 도망치다가

내 항아리 파일 안에는 업로드라는 폴더가 있었고, 이 폴더에는 세 개의 다른 텍스트 파일이 들어 있었다. 항아리 파일 외부에 정확히 동일한 폴더와 파일이 있어야 했다. 나는 아래 코드를 사용했다.

URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);

URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);

URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

단순함...OSGi를 사용하다.OSGi에서는 findEntries 및 findPaths로 번들 항목을 반복할 수 있다.

링크는 방법을 알려준다.

마법은 getResourceAsStream() 메서드:

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")

참조URL: https://stackoverflow.com/questions/11012819/how-can-i-access-a-folder-inside-of-a-resource-folder-from-inside-my-jar-file

반응형