classpath 디렉토리에서 리소스 목록을 가져옵니다.
지정된 클래스 경로 디렉토리에서 모든 리소스 이름 목록을 가져오는 방법(메서드 등)을 찾고 있습니다.List<String> getResourceNames (String directoryName)
.
예를 들어 classpath 디렉토리가 지정됩니다.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의 리소스 모두에 대해 작동합니다.
제가 짧은 글을 쓸 수 있다는 걸 알아요File
s,JarFile
및URL
s, 하지만 바퀴를 다시 만들고 싶지는 않습니다.질문입니다만, 기존의 공개 라이브러리를 고려할 때, 구현이 가장 빠른 방법은 무엇입니까?getResourceNames
? 스프링 및 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();
}
스프링 프레임워크
스프링 프레임워크에서 사용합니다.
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을 사용하는 경우 Path Matching Resource Pattern Resolver를 참조하십시오.
리플렉션 사용
클래스 패스에 있는 모든 것을 가져옵니다.
Reflections reflections = new Reflections(null, new ResourcesScanner());
Set<String> resourceList = reflections.getResources(x -> true);
다른 예로는 확장자가 .csv인 모든 파일을 some.package에서 가져옵니다.
Reflections reflections = new Reflections("some.package", new ResourcesScanner());
Set<String> resourceList = reflections.getResources(Pattern.compile(".*\\.csv"));
PathMatchingResourcePatternResolver의 관점에서 코드에 필요한 것은 다음과 같습니다.
@Autowired
ResourcePatternResolver resourceResolver;
public void getResources() {
resourceResolver.getResources("classpath:config/*.xml");
}
Apache Commons를 사용하는 경우파일 시스템에 사용할 수 있는 IO(옵션 확장 필터 사용):
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)
두 가지를 조합하여 사용할 수 있습니다.
ClassPath 내의 모든 리소스를 나열하는 가장 강력한 메커니즘은 현재 ClassGraph에서 이 패턴을 사용하는 것입니다.이는 새로운 JPMS 모듈 시스템을 포함하여 가능한 한 광범위한 클래스 경로 지정 메커니즘을 처리하기 때문입니다.(Class Graph의 저자입니다.)
List<String> resourceNames;
try (ScanResult scanResult = new ClassGraph().whitelistPaths("x/y/z").scan()) {
resourceNames = scanResult.getAllResources().getNames();
}
그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");
}
Maven 의존관계:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>LATEST</version>
</dependency>
이 방법은 작동해야 합니다(스프링 옵션이 아닌 경우).
public static List<String> getFilenamesForDirnameFromCP(String directoryName) throws URISyntaxException, UnsupportedEncodingException, IOException {
List<String> filenames = new ArrayList<>();
URL url = Thread.currentThread().getContextClassLoader().getResource(directoryName);
if (url != null) {
if (url.getProtocol().equals("file")) {
File file = Paths.get(url.toURI()).toFile();
if (file != null) {
File[] files = file.listFiles();
if (files != null) {
for (File filename : files) {
filenames.add(filename.toString());
}
}
}
} else if (url.getProtocol().equals("jar")) {
String dirname = directoryName + "/";
String path = url.getPath();
String jarPath = path.substring(5, path.indexOf("!"));
try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, StandardCharsets.UTF_8.name()))) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.startsWith(dirname) && !dirname.equals(name)) {
URL resource = Thread.currentThread().getContextClassLoader().getResource(name);
filenames.add(resource.toString());
}
}
}
}
}
return filenames;
}
My way, no spring(스프링 없음)은 유닛 테스트 중에 사용됩니다.
URI uri = TestClass.class.getResource("/resources").toURI();
Path myPath = Paths.get(uri);
Stream<Path> walk = Files.walk(myPath, 1);
for (Iterator<Path> it = walk.iterator(); it.hasNext(); ) {
Path filename = it.next();
System.out.println(filename);
}
봄과 함께라면 쉽다.하나의 파일, 폴더, 또는 여러 개의 파일 모두 주입을 통해 실행할 수 있습니다.
에서는 에 있는 여러 줍니다.x/y/z
더입니니다다
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
@Service
public class StackoverflowService {
@Value("classpath:x/y/z/*")
private Resource[] resources;
public List<String> getResourceNames() {
return Arrays.stream(resources)
.map(Resource::getFilename)
.collect(Collectors.toList());
}
}
파일 시스템 내의 리소스와 JAR 내의 리소스에 대해 동작합니다.
롭의 반응을 조합해서 사용했어
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
}
이를 위해 [Zip 파일 시스템 공급자][1]를 활용할 수 있습니다.사용시FileSystems.newFileSystem
를 "할 수 것 .ZIP 내의 오브젝트를 "일반" 파일로 취급할 수 있을 것 같습니다.
위의 링크된 문서에서 다음을 수행합니다.
으로 지정합니다util은 zip 파일시스템 설정 옵션을 합니다.가 " "에 전달되었습니다.
FileSystems.newFileSystem
파일 에 대한 은 [ 시스템] zip 파일 시스템의 공급자별 구성 속성에 대한 자세한 내용은 [Zip 파일 시스템 속성][2] 항목을 참조하십시오.[zip ]의 메서드를 할 수 .
java.nio.file.FileSystem
[ ][ 3 ] [ [ [ ]java.nio.file.Path
파일 속성 변경 및 파일 복사, 이동 및 이름 변경 등의 작업을 수행하는 클래스입니다.
『 』의 jdk.zipfs
[자바 11개 상태][5] 듈 :
zip의 할 수 .[zip ]으로 작성할 수 .
FileSystems.newFileSystem
[6] (영어)
다음은 제가 귀사의 예제 리소스를 사용하여 만든 예입니다.과 같습니다..zip
는 입니다..jar
, 리소스를 대신 하도록 코드를 조정할 수 classpath:, 、 classpath 、 classpath 、 classpath 、 classpath 、 classpath 、 classpath 、 classpath の , , , , , , 。
세우다
cd /tmp
mkdir -p x/y/z
touch x/y/z/{a,b,c}.html
echo 'hello world' > x/y/z/d
zip -r example.zip x
자바
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.Collections;
import java.util.stream.Collectors;
public class MkobitZipRead {
public static void main(String[] args) throws IOException {
final URI uri = URI.create("jar:file:/tmp/example.zip");
try (
final FileSystem zipfs = FileSystems.newFileSystem(uri, Collections.emptyMap());
) {
Files.walk(zipfs.getPath("/")).forEach(path -> System.out.println("Files in zip:" + path));
System.out.println("-----");
final String manifest = Files.readAllLines(
zipfs.getPath("x", "y", "z").resolve("d")
).stream().collect(Collectors.joining(System.lineSeparator()));
System.out.println(manifest);
}
}
}
산출량
Files in zip:/
Files in zip:/x/
Files in zip:/x/y/
Files in zip:/x/y/z/
Files in zip:/x/y/z/c.html
Files in zip:/x/y/z/b.html
Files in zip:/x/y/z/a.html
Files in zip:/x/y/z/d
-----
hello world
리소스를 리소스 폴더에 넣고 위의 답변을 따라했는데도 두 답변 모두 작동하지 않았습니다.트릭을 만든 것은 다음과 같습니다.
@Value("file:*/**/resources/**/schema/*.json")
private Resource[] resources;
위의 @rob의 정보를 바탕으로 퍼블릭 도메인에 공개하는 구현을 작성했습니다.
private static List<String> getClasspathEntriesByPath(String path) throws IOException {
InputStream is = Main.class.getClassLoader().getResourceAsStream(path);
StringBuilder sb = new StringBuilder();
while (is.available()>0) {
byte[] buffer = new byte[1024];
sb.append(new String(buffer, Charset.defaultCharset()));
}
return Arrays
.asList(sb.toString().split("\n")) // Convert StringBuilder to individual lines
.stream() // Stream the list
.filter(line -> line.trim().length()>0) // Filter out empty lines
.collect(Collectors.toList()); // Collect remaining lines into a List again
}
getResourcesAsStream
디렉토리에서 이렇게 작업하는 것은 정말 잘 작동하고 잘 작동합니다.
언급URL : https://stackoverflow.com/questions/3923129/get-a-list-of-resources-from-classpath-directory
'programing' 카테고리의 다른 글
구성 요소 재렌더에서 Vue.js 무한 루프 (0) | 2022.08.28 |
---|---|
돌연변이에 대한 Vuex 도우미 메서드 (0) | 2022.08.28 |
jar로 실행할 때 클래스 경로 리소스를 찾을 수 없음 (0) | 2022.08.28 |
상태가 업데이트될 때 구성 요소가 다시 렌더링되지 않음 (0) | 2022.08.28 |
"../include/header"와 같은 상대 경로의 이점은 무엇입니까?h"는 헤더에 사용할 수 있습니까? (0) | 2022.08.28 |