获取资源包内所有文件名,适配Jar与非Jar运行场景
兼容Jar包与开发环境的资源目录文件遍历方案
嘿,我之前做Java桌面应用的时候也踩过这个资源读取的坑,刚好能给你一个靠谱的解决方案。核心思路是区分当前运行环境是文件系统(开发时)还是Jar包内,然后分别处理文件遍历逻辑:
核心实现步骤
- 获取目标资源目录的URL,通过
Class.getResource()方法,注意路径要以/开头,对应项目的resources根目录 - 根据URL的协议(
file或jar)判断运行环境 - 针对不同环境实现文件遍历:
- 开发环境(file协议):直接用
File类遍历目录 - Jar包环境(jar协议):通过
JarURLConnection获取Jar文件,遍历其中的条目筛选目标文件
- 开发环境(file协议):直接用
完整代码示例
import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class PresetLoader { private static final String PRESET_DIR_PATH = "/resources/presets/"; private static final String FILE_EXTENSION = ".txt"; public List<String> getPresetFileNames() throws IOException { List<String> presetFiles = new ArrayList<>(); URL dirUrl = getClass().getResource(PRESET_DIR_PATH); if (dirUrl == null) { throw new IOException("预设目录不存在: " + PRESET_DIR_PATH); } switch (dirUrl.getProtocol()) { case "file": // 开发环境:直接遍历文件系统目录 File dir = new File(dirUrl.getFile()); if (dir.isDirectory()) { File[] files = dir.listFiles((d, name) -> name.endsWith(FILE_EXTENSION)); if (files != null) { for (File file : files) { presetFiles.add(file.getName()); } } } break; case "jar": // Jar包环境:解析Jar文件遍历条目 JarURLConnection jarConn = (JarURLConnection) dirUrl.openConnection(); try (JarFile jarFile = jarConn.getJarFile()) { Enumeration<JarEntry> entries = jarFile.entries(); String presetDir = PRESET_DIR_PATH.substring(1); // 去掉开头的/,匹配Jar内路径 while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); // 筛选出预设目录下的txt文件,且不是目录本身 if (entryName.startsWith(presetDir) && entryName.endsWith(FILE_EXTENSION) && !entry.isDirectory()) { // 只提取文件名,去掉路径前缀 String fileName = entryName.substring(presetDir.length()); presetFiles.add(fileName); } } } break; default: throw new IOException("不支持的资源协议: " + dirUrl.getProtocol()); } return presetFiles; } }
关键注意事项
- 路径正确性:
PRESET_DIR_PATH必须以/开头,确保指向resources根目录下的presets文件夹,不管是开发环境还是Jar包内都能正确定位 - 打包配置:如果用Maven/Gradle构建,要确保
src/main/resources/presets目录被正确打包进Jar。比如Maven的pom.xml里默认会包含resources目录,不用额外配置;如果是自定义结构,要在build的resources节点里添加包含规则 - 资源关闭:JarFile要放在try-with-resources块里自动关闭,避免资源泄漏
- 异常处理:实际使用时可以根据业务需求调整异常抛出逻辑,比如返回空列表而不是抛出异常
这样不管你是在IDE里运行开发,还是打包成Jar后运行,都能正确获取到所有预设关卡的txt文件名啦!
内容的提问来源于stack exchange,提问作者Scorix




