You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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,通过读取清单来获取文件名列表:

  1. 生成清单文件:在src/main/resources/portraits目录下创建portraits.list,每行写入一个文件名(可通过Maven/Gradle构建脚本自动生成,避免手动维护)。
  2. 读取清单代码:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 00:45:13