[java] 클래스 경로 디렉토리에서 자원 목록 가져 오기

주어진 클래스 경로 디렉토리에서 메소드와 같은 모든 리소스 이름 목록을 얻는 방법을 찾고 List<String> getResourceNames (String directoryName)있습니다.

예를 들어, 클래스 경로 디렉토리 주어진 x/y/z파일 포함 a.html, b.html, c.html및 하위 디렉토리를 d, getResourceNames("x/y/z")A는 반환해야합니다 List<String>다음과 같은 문자열을 포함 : ['a.html', 'b.html', 'c.html', 'd'].

파일 시스템 및 jar의 자원 모두에서 작동해야합니다.

Files, JarFiles 및 URLs 로 빠른 스 니펫을 작성할 수 있지만 바퀴를 재발 명하고 싶지 않습니다. 내 질문은 기존의 공개 라이브러리를 고려할 때 구현하는 가장 빠른 방법은 무엇 getResourceNames입니까? Spring과 Apache Commons 스택은 모두 가능합니다.



답변

맞춤형 스캐너

자신의 스캐너를 구현하십시오. 예를 들면 다음과 같습니다.

private List<String> getResourceFiles(String path) throws IOException {
    List<String> filenames = new ArrayList<>();

    try (
            InputStream in = getResourceAsStream(path);
            BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
        String resource;

        while ((resource = br.readLine()) != null) {
            filenames.add(resource);
        }
    }

    return filenames;
}

private InputStream getResourceAsStream(String resource) {
    final InputStream in
            = getContextClassLoader().getResourceAsStream(resource);

    return in == null ? getClass().getResourceAsStream(resource) : in;
}

private ClassLoader getContextClassLoader() {
    return Thread.currentThread().getContextClassLoader();
}

스프링 프레임 워크

PathMatchingResourcePatternResolverSpring Framework에서 사용하십시오 .

Ronmamo 반사

다른 CLASSPATH 값은 런타임에 느릴 수 있습니다. 더 빠른 해결책은 컴파일 타임에 검색을 사전 컴파일하는 ronmamo의 Reflections API 를 사용하는 것 입니다.


답변

여기에 코드입니다
출처 : forums.devx.com/showthread.php?t=153784

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
 * list resources available from the classpath @ *
 */
public class ResourceList{

    /**
     * for all elements of java.class.path get a Collection of resources Pattern
     * pattern = Pattern.compile(".*"); gets all resources
     * 
     * @param pattern
     *            the pattern to match
     * @return the resources in the order they are found
     */
    public static Collection<String> getResources(
        final Pattern pattern){
        final ArrayList<String> retval = new ArrayList<String>();
        final String classPath = System.getProperty("java.class.path", ".");
        final String[] classPathElements = classPath.split(System.getProperty("path.separator"));
        for(final String element : classPathElements){
            retval.addAll(getResources(element, pattern));
        }
        return retval;
    }

    private static Collection<String> getResources(
        final String element,
        final Pattern pattern){
        final ArrayList<String> retval = new ArrayList<String>();
        final File file = new File(element);
        if(file.isDirectory()){
            retval.addAll(getResourcesFromDirectory(file, pattern));
        } else{
            retval.addAll(getResourcesFromJarFile(file, pattern));
        }
        return retval;
    }

    private static Collection<String> getResourcesFromJarFile(
        final File file,
        final Pattern pattern){
        final ArrayList<String> retval = new ArrayList<String>();
        ZipFile zf;
        try{
            zf = new ZipFile(file);
        } catch(final ZipException e){
            throw new Error(e);
        } catch(final IOException e){
            throw new Error(e);
        }
        final Enumeration e = zf.entries();
        while(e.hasMoreElements()){
            final ZipEntry ze = (ZipEntry) e.nextElement();
            final String fileName = ze.getName();
            final boolean accept = pattern.matcher(fileName).matches();
            if(accept){
                retval.add(fileName);
            }
        }
        try{
            zf.close();
        } catch(final IOException e1){
            throw new Error(e1);
        }
        return retval;
    }

    private static Collection<String> getResourcesFromDirectory(
        final File directory,
        final Pattern pattern){
        final ArrayList<String> retval = new ArrayList<String>();
        final File[] fileList = directory.listFiles();
        for(final File file : fileList){
            if(file.isDirectory()){
                retval.addAll(getResourcesFromDirectory(file, pattern));
            } else{
                try{
                    final String fileName = file.getCanonicalPath();
                    final boolean accept = pattern.matcher(fileName).matches();
                    if(accept){
                        retval.add(fileName);
                    }
                } catch(final IOException e){
                    throw new Error(e);
                }
            }
        }
        return retval;
    }

    /**
     * list the resources that match args[0]
     * 
     * @param args
     *            args[0] is the pattern to match, or list all resources if
     *            there are no args
     */
    public static void main(final String[] args){
        Pattern pattern;
        if(args.length < 1){
            pattern = Pattern.compile(".*");
        } else{
            pattern = Pattern.compile(args[0]);
        }
        final Collection<String> list = ResourceList.getResources(pattern);
        for(final String name : list){
            System.out.println(name);
        }
    }
}  

Spring을 사용하는 경우 PathMatchingResourcePatternResolver를 살펴보십시오 .


답변

반사 사용

클래스 패스에있는 모든 것을 얻는다 :

Reflections reflections = new Reflections(null, new ResourcesScanner());
Set<String> resourceList = reflections.getResources(x -> true);

또 다른 예 -some.package 에서 확장자가 .csv 인 모든 파일을 가져 옵니다 .

Reflections reflections = new Reflections("some.package", new ResourcesScanner());
Set<String> fileNames = reflections.getResources(Pattern.compile(".*\\.csv"));


답변

Apache CommonsIO를 사용하는 경우 파일 시스템에 사용할 수 있습니다 (선택적으로 확장 필터 사용)

Collection<File> files = FileUtils.listFiles(new File("directory/"), null, false);

리소스 / 클래스 패스의 경우 :

List<String> files = IOUtils.readLines(MyClass.class.getClassLoader().getResourceAsStream("directory/"), Charsets.UTF_8);

“directoy /”가 파일 시스템에 있는지 또는 리소스에 있는지 모르는 경우

if (new File("directory/").isDirectory())

또는

if (MyClass.class.getClassLoader().getResource("directory/") != null)

통화하기 전에 두 가지를 함께 사용하십시오 …


답변

따라서 PathMatchingResourcePatternResolver의 관점에서 이것은 코드에서 필요한 것입니다.

@Autowired
ResourcePatternResolver resourceResolver;

public void getResources() {
  resourceResolver.getResources("classpath:config/*.xml");
}


답변

Spring framework의는 PathMatchingResourcePatternResolver이러한 것들을 정말 굉장합니다 :

private Resource[] getXMLResources() throws IOException
{
    ClassLoader classLoader = MethodHandles.lookup().getClass().getClassLoader();
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);

    return resolver.getResources("classpath:x/y/z/*.xml");
}

메이븐 의존성 :

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>LATEST</version>
</dependency>


답변

Rob의 응답 조합을 사용했습니다.

final String resourceDir = "resourceDirectory/";
List<String> files = IOUtils.readLines(Thread.currentThread().getClass().getClassLoader().getResourceAsStream(resourceDir), Charsets.UTF_8);

for(String f : files){
  String data= IOUtils.toString(Thread.currentThread().getClass().getClassLoader().getResourceAsStream(resourceDir + f));
  ....process data
}