使用jpackage打包Java后相对路径失效问题求助
jpackage打包后获取资源文件夹文件列表的解决方案
问题根源
jpackage打包后,项目资源会被封装到Jar包或应用镜像内部,不再是操作系统文件系统中的独立文件夹,因此IDE中可用的相对文件路径会失效。
可行解决方案
方案1:解析Jar包内的资源路径
通过类加载器获取资源URL,判断协议类型后分别处理IDE运行(文件系统)和打包后(Jar包)的场景:
import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ResourceLoader { public List<String> getPortraitFiles() { List<String> fileList = new ArrayList<>(); URL resourceUrl = ResourceLoader.class.getClassLoader().getResource("portraits/"); if (resourceUrl == null) { return fileList; } try { if ("jar".equals(resourceUrl.getProtocol())) { // 处理Jar包内的资源 String jarPath = resourceUrl.getPath().substring(5, resourceUrl.getPath().indexOf("!")); JarFile jarFile = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); // 筛选portraits目录下的非目录文件 if (entryName.startsWith("portraits/") && !entry.isDirectory()) { String fileName = entryName.substring("portraits/".length()); fileList.add(fileName); } } jarFile.close(); } else if ("file".equals(resourceUrl.getProtocol())) { // 处理IDE运行时的文件系统路径 File folder = new File(resourceUrl.toURI()); File[] files = folder.listFiles(); if (files != null) { for (File file : files) { if (!file.isDirectory()) { fileList.add(file.getName()); } } } } } catch (Exception e) { e.printStackTrace(); } return fileList; } }
方案2:预生成资源清单文件(更简单稳定)
提前将资源文件夹内的文件名整理成一个清单文件,打包时随资源一起放入Jar,通过读取清单来获取文件名列表:
- 生成清单文件:在
src/main/resources/portraits目录下创建portraits.list,每行写入一个文件名(可通过Maven/Gradle构建脚本自动生成,避免手动维护)。 - 读取清单代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class ResourceLoader { public List<String> getPortraitFiles() { List<String> fileList = new ArrayList<>(); try (InputStream is = ResourceLoader.class.getClassLoader().getResourceAsStream("portraits/portraits.list"); BufferedReader br = new BufferedReader(new InputStreamReader(is))) { String line; while ((line = br.readLine()) != null) { String fileName = line.trim(); if (!fileName.isEmpty()) { fileList.add(fileName); } } } catch (IOException e) { e.printStackTrace(); } return fileList; } }
注意事项
- 确保资源文件夹(如
portraits)被正确配置到构建工具的资源目录中(Maven默认src/main/resources,Gradle默认src/main/resources),保证打包时能被纳入Jar包。 - 始终使用类加载器的
getResource()或getResourceAsStream()方法访问资源,避免硬编码绝对路径或依赖文件系统的相对路径。
内容的提问来源于stack exchange,提问作者Potat.OS1
相关产品推荐
相关产品推荐

