所以,我相信这个问题已经被问过一百万次了,我已经阅读了几个小时并尝试了一些人给出的几种选择,但没有一个对我有用。
我想列出应用程序 JAR 内某个目录内的所有文件,因此在 IDE 中这是可行的:
File f = new File(this.getClass().getResource("/resources/").getPath());
for(String s : f.list){
System.out.println(s);
}
这给了我目录中的所有文件。
现在,我也尝试过:
InputStream in = this.getClass().getClassLoader().getResourceAsStream("resources/");
InputStreamReader inReader = new InputStreamReader(in);
Scanner scan = new Scanner(inReader);
while (scan.hasNext()) {
String s = scan.next();
System.out.println("read: " + s);
}
System.out.println("END OF LINE");
从 IDE 中,它会打印目录中的所有文件。外部 IDE 打印:“END OF LINE”。
现在,我也可以在 Jar 中找到一个条目:
String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
JarFile jar = new JarFile(s);
JarEntry entry = jar.getJarEntry("resources");
if (entry != null){
System.out.println("EXISTS");
System.out.println(entry.getSize());
}
我必须对该字符串进行一些可怕的编码。
无论如何...我无法获取 Jar 中“资源”目录内的资源列表...我该怎么做???
如果不首先枚举 Jar 文件的内容,就无法简单地获取内部资源的过滤列表。
幸运的是,这实际上并不难(对我来说幸运的是你已经完成了大部分艰苦的工作)。
基本上,一旦您引用了
JarFile
,您只需询问其' entries
并迭代该列表即可。
通过检查所需匹配的
JarEntry
名称(即resources
),您可以过滤您想要的元素...
例如...
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReadMyResources {
public static void main(String[] args) {
new ReadMyResources();
}
public ReadMyResources() {
JarFile jf = null;
try {
String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
jf = new JarFile(s);
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
if (je.getName().startsWith("resources")) {
System.out.println(je.getName());
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
jf.close();
} catch (Exception e) {
}
}
}
}
注意事项
这种类型的问题实际上有人问过。与其尝试在运行时读取 Jar 的内容,不如生成某种包含可用资源列表的文本文件。
这可以在创建 Jar 文件之前由构建过程动态生成。然后读取此文件(例如,通过
getClass().getResource()
),然后查找文本文件中的每个资源列表,这将是一个更简单的解决方案...恕我直言
PathMatchingResourcePatternResolver
执行以下操作:
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:path/to/resource/*.*");
for (Resource resource : resources) {
InputStream inStream = resource.getInputStream();
// Do something with the input stream
}
我的情况是读取资源内的目录:
由于我的需求是将资源目录转换为io.File,最后看起来像这样:
public static File getResourceDirectory(String resource) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL res = classLoader.getResource(resource);
File fileDirectory;
if ("jar".equals(res.getProtocol())) {
InputStream input = classLoader.getResourceAsStream(resource);
fileDirectory = Files.createTempDir();
List<String> fileNames = IOUtils.readLines(input, StandardCharsets.UTF_8);
fileNames.forEach(name -> {
String fileResourceName = resource + File.separator + name;
File tempFile = new File(fileDirectory.getPath() + File.pathSeparator + name);
InputStream fileInput = classLoader.getResourceAsStream(resourceFileName);
FileUtils.copyInputStreamToFile(fileInput, tempFile);
});
fileDirectory.deleteOnExit();
} else {
fileDirectory = new File(res.getFile());
}
return fileDirectory;
}
如果资源在jar中,我们将其复制到临时目录中,该目录将在应用程序端删除。 然后调用
getResourceDirectory("migrations")
返回给我 io.File
目录以供进一步使用。