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

Java:如何列出Jar包中resources目录下的直接子目录

解决Maven项目中IDE与Jar环境兼容的资源目录子项获取问题

我之前也踩过这个坑——IDE里跑起来顺风顺水的代码,打包成Jar就直接失效,核心原因就是两种环境下资源的存储逻辑完全不一样:IDE里是真实的文件系统目录,而Jar里是压缩包内的条目。下面给你一套能同时兼容两种场景的解决方案,专门用来获取dir1的直接子目录名称(比如你的subdir1、subdir2):

核心实现代码

这里写一个工具类,把两种环境的处理逻辑封装起来:

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class ResourceDirectoryUtils {

    public static List<String> getDirectSubdirectories(String parentDir) throws IOException, URISyntaxException {
        List<String> subDirNames = new ArrayList<>();
        // 获取目标目录的资源URL
        URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource(parentDir);
        if (resourceUrl == null) {
            throw new IllegalArgumentException("指定的目录不存在: " + parentDir);
        }

        URI resourceUri = resourceUrl.toURI();
        // 区分是文件系统资源(IDE环境)还是Jar包内资源
        if ("file".equals(resourceUri.getScheme())) {
            // IDE环境:直接操作本地文件系统
            Path parentPath = Paths.get(resourceUri);
            // 遍历目录,过滤出子目录并收集名称
            try (Stream<Path> pathStream = Files.list(parentPath)) {
                pathStream.filter(Files::isDirectory)
                          .map(path -> path.getFileName().toString())
                          .forEach(subDirNames::add);
            }
        } else if ("jar".equals(resourceUri.getScheme())) {
            // Jar包环境:创建临时文件系统访问Jar内条目
            FileSystem jarFileSystem = FileSystems.newFileSystem(resourceUri, null);
            Path parentPath = jarFileSystem.getPath(parentDir);
            try (Stream<Path> pathStream = Files.list(parentPath)) {
                pathStream.filter(Files::isDirectory)
                          .map(path -> path.getFileName().toString())
                          .forEach(subDirNames::add);
            } finally {
                // 用完记得关闭文件系统,避免资源泄漏
                jarFileSystem.close();
            }
        } else {
            throw new UnsupportedOperationException("不支持的资源类型: " + resourceUri.getScheme());
        }

        return subDirNames;
    }

    // 测试用例,直接运行就能看到结果
    public static void main(String[] args) {
        try {
            List<String> subDirs = getDirectSubdirectories("dir1");
            System.out.println("dir1的直接子目录:");
            subDirs.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关键细节说明

  • 类加载器选择:用Thread.currentThread().getContextClassLoader()而不是当前类的getResource(),能适配更复杂的类加载场景(比如模块化项目、自定义类加载器)
  • 环境区分逻辑:通过URI的scheme判断是file(IDE本地文件)还是jar(压缩包内资源),分别处理
  • Jar环境的特殊处理:Jar包本质是压缩文件,需要创建临时的FileSystem才能像访问本地目录一样遍历内部条目,用完必须关闭
  • 资源路径正确性:默认情况下Maven会把src/main/resources下的内容打包到Jar根目录,所以调用时直接传dir1即可;如果你的Maven资源配置有自定义路径,要对应调整参数

注意事项

  • 确保Maven的pom.xml没有排除dir1及其子目录,默认的资源配置会包含所有src/main/resources下的内容
  • 异常处理可以根据业务需求调整,比如返回空列表而不是抛出异常,或者添加日志输出
  • 如果是JDK9+的模块化项目,需要在module-info.java中添加对java.nio.file的依赖

内容的提问来源于stack exchange,提问作者lubik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:59:03