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

Java项目在IDEA中可加载图片,打包为Jar后无法加载的问题

Jaylib打包Jar后无法加载图片资源的解决办法

问题根源

Jar本质是压缩归档文件,里面的资源并非本地文件系统里的真实文件。你当前用Path.of(URI)获取路径的方式,在IDEA运行时能正常工作——因为此时资源是散落在磁盘上的普通文件,但打包成Jar后,资源被封装在Zip格式的Jar包内,Path无法直接指向Jar内部的资源,这就导致了日志里的ZipFileSystem相关报错。

可行解决方案

方案1:把Jar内资源转成临时文件再加载

Jaylib的纹理加载大多依赖本地文件路径,所以可以先将Jar里的资源读为输入流,写入临时文件,再用临时文件的路径加载:

@Nullable
public String getTempFilePath() {
    try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(this.location)) {
        if (inputStream == null) {
            LOGGER.error("找不到资源:{}", this.location);
            return null;
        }
        // 保留原资源扩展名,避免Jaylib识别格式出错
        String extension = location.substring(location.lastIndexOf('.'));
        File tempFile = File.createTempFile("temp-res-", extension);
        tempFile.deleteOnExit(); // 程序退出时自动清理临时文件,避免残留

        // 将输入流内容写入临时文件
        Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        return tempFile.getAbsolutePath();
    } catch (IOException e) {
        LOGGER.error("创建临时文件失败", e);
        return null;
    }
}

加载纹理时使用这个临时路径即可:

String tempPath = resourceLocation.getTempFilePath();
if (tempPath != null) {
    Texture texture = LoadTexture(tempPath);
    // 后续使用纹理的逻辑...
}

方案2:直接从内存加载(如果Jaylib支持)

如果Jaylib提供了从内存加载的API(比如LoadImageFromMemory搭配LoadTextureFromImage),可以直接读取资源的字节数组来加载,无需创建临时文件:

@Nullable
public byte[] getResourceBytes() {
    try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(this.location)) {
        if (inputStream == null) {
            LOGGER.error("找不到资源:{}", this.location);
            return null;
        }
        return inputStream.readAllBytes();
    } catch (IOException e) {
        LOGGER.error("读取资源失败", e);
        return null;
    }
}

加载纹理的代码示例:

byte[] imgBytes = resourceLocation.getResourceBytes();
if (imgBytes != null) {
    // 第二个参数为图片格式后缀,根据你的资源修改,比如".jpg"
    Image img = LoadImageFromMemory(".png", imgBytes, imgBytes.length);
    Texture texture = LoadTextureFromImage(img);
    UnloadImage(img); // 加载完纹理后可释放Image对象
    // 使用纹理的逻辑...
}

注意事项

  • 确认资源路径location为正确的类路径相对路径,比如textures/player.png,使用getClassLoader().getResourceAsStream时不要加开头的/。
  • 临时文件方案中的deleteOnExit()能保证程序正常退出时清理文件,即便异常终止也只会残留少量临时文件,影响极小。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:35:11