如何从Jar包的resources中获取文件或目录列表?
从Jar包的resources中获取文件或目录列表
下面两种常见方法可以实现需求,同时兼容开发环境(本地文件系统)和Jar包运行环境:
方法一:通过ClassLoader解析Jar文件
Jar包本质是压缩文件,无法用普通File类直接访问,需要借助JarFile遍历条目:
import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ResourceScanner { public static void scanResources(String targetPath) throws IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL resourceUrl = classLoader.getResource(targetPath); if (resourceUrl == null) { System.out.println("目标路径不存在:" + targetPath); return; } String protocol = resourceUrl.getProtocol(); if ("jar".equals(protocol)) { JarURLConnection jarConn = (JarURLConnection) resourceUrl.openConnection(); JarFile jarFile = jarConn.getJarFile(); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); // 筛选目标路径下的资源,排除路径本身 if (entryName.startsWith(targetPath) && !entryName.equals(targetPath)) { if (entry.isDirectory()) { // 提取目录名,去除前缀和末尾斜杠 String dirName = entryName.substring(targetPath.length()).replaceFirst("^/", "").replaceAll("/$", ""); if (!dirName.isEmpty()) { System.out.println("目录:" + dirName); } } else { // 提取文件名 String fileName = entryName.substring(entryName.lastIndexOf("/") + 1); System.out.println("文件:" + fileName); } } } jarFile.close(); } else if ("file".equals(protocol)) { // 开发环境直接遍历本地目录 java.io.File dir = new java.io.File(resourceUrl.getFile()); if (dir.isDirectory()) { String[] names = dir.list(); if (names != null) { for (String name : names) { java.io.File item = new java.io.File(dir, name); System.out.println(item.isDirectory() ? "目录:" + name : "文件:" + name); } } } } } public static void main(String[] args) throws IOException { // 示例:获取resources下insights目录的内容 scanResources("insights"); // 示例:获取resources下存放json文件的目录内容 scanResources("json_data"); } }
方法二:用NIO FileSystem简化操作(Java 7+)
Java 7引入的FileSystem API可以把Jar包当作独立文件系统处理,代码更简洁:
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.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; public class NioResourceScanner { public static void scanResources(String targetPath) throws IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL resourceUrl = classLoader.getResource(targetPath); if (resourceUrl == null) { System.out.println("目标路径不存在:" + targetPath); return; } String protocol = resourceUrl.getProtocol(); if ("jar".equals(protocol)) { // 解析Jar文件路径,格式为jar:file:/xxx.jar!/path String jarPath = resourceUrl.getPath().substring(5, resourceUrl.getPath().indexOf("!")); URI jarUri = URI.create("jar:file:" + jarPath); try (FileSystem jarFs = FileSystems.newFileSystem(jarUri, Collections.emptyMap())) { Path path = jarFs.getPath(targetPath); if (Files.exists(path)) { Files.list(path).forEach(item -> { String name = item.getFileName().toString(); System.out.println(Files.isDirectory(item) ? "目录:" + name : "文件:" + name); }); } } } else if ("file".equals(protocol)) { // 开发环境遍历本地目录 Path path = Paths.get(resourceUrl.getFile()); if (Files.isDirectory(path)) { Files.list(path).forEach(item -> { String name = item.getFileName().toString(); System.out.println(Files.isDirectory(item) ? "目录:" + name : "文件:" + name); }); } } } public static void main(String[] args) throws IOException { scanResources("openapi"); scanResources("daily_json"); } }
关键注意点
- 打包时确保resources目录下的内容被正确包含,Maven/Gradle默认会处理,但自定义配置时要检查。
- 路径用斜杠
/分隔,不要加末尾斜杠(比如用"insights"而非"insights/"),避免筛选逻辑出错。 - Jar包内的资源是只读的,只能读取不能修改。
内容的提问来源于stack exchange,提问作者buddha
相关产品推荐
相关产品推荐

