awa1024 2025-08-05 19:38 采纳率: 100%
浏览 5
已结题

emscripten提示找不到data目录

img

img


我想移植一个游戏到网页上,搞到了c语言源码和exe文件,并用emscripten编译了源码,得到了一个html,一个js,一个wasm。后来我发现源码里没有data目录,就从exe文件里找了个data.bin,看类型是zip,我就解压了,解压后还打开看了一眼,都是正常的。我把data目录放进html文件所在的文件夹,运行python -m http.server后就出现如图所示的报错,可是我明明有data文件啊?我开了无痕浏览,所以不是缓存问题。求解

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-08-05 19:39
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你遇到的问题是关于 Emscripten 编译后游戏在网页上运行时提示找不到 data 目录。虽然你已经将 data 文件夹放到了 HTML 文件所在的目录中,但仍然报错,这可能是因为 Emscripten 的文件系统加载方式 和你的本地文件结构不匹配。


    ✅ 问题分析

    1. Emscripten 默认使用虚拟文件系统(FS)
      Emscripten 在编译时会将一些资源(如 data 文件)打包进 .wasm.js 文件中,或者通过 预加载机制 加载外部文件。

    2. data.bin 是 ZIP 格式,可能是资源包
      你从 .exe 中提取的 data.bin 实际上是一个 ZIP 压缩包,里面包含了游戏所需的资源文件(图片、声音等),但 它并不是一个“目录”,而是一个压缩文件。

    3. HTML 文件和 data 目录不在同一个路径下
      虽然你把 data 放到了 HTML 所在的目录,但 Emscripten 可能期望的是 相对路径或特定的加载方式,而不是简单的文件夹。

    4. 没有正确配置 Emscripten 的资源加载路径
      如果你在编译时没有设置正确的路径,或者没有使用 --preload-file 参数,那么 Emscripten 无法自动加载 data 目录。


    🔧 解决方案

    1. 确认 data.bin 的用途

    • 使用解压工具(如 7-Zip 或 WinRAR)打开 data.bin,确认其中是否包含游戏资源。
    • 如果它是 ZIP 文件,尝试将其重命名为 data.zip 并放在 HTML 同级目录中。

    2. 使用 --preload-file 参数重新编译

    如果你还没有用 --preload-file 预加载 data.zip,请重新编译源码:

    emcc -O3 -s WASM=1 -s EXPORTED_FUNCTIONS="['_main']" -s EXPORTED_RUNTIME_METHODS="['cwrap', 'getValue', 'Pointer_stringify']" \
         -s "MODULARIZE=1" -s "EXPORT_NAME='Game'"\ 
         -s "PRELOAD_FILE=data.zip:/" \
         your_source.c -o game.html
    

    注意: -s PRELOAD_FILE=data.zip:/ 表示将 data.zip 作为根目录 / 加载到虚拟文件系统中。

    3. 修改 HTML 文件中的资源路径

    确保 HTML 文件中引用了正确的路径。例如:

    <script src="game.js"></script>
    

    并确保 data.zipgame.js 在同一目录下。

    4. 检查 JavaScript 控制台错误信息

    打开浏览器的开发者工具(F12),查看控制台是否有以下错误:

    • Failed to load resource: the server responded with a 404
    • Uncaught Error: Could not find data file
    • File not found in FS: /data/...

    这些信息可以帮助你定位具体缺失的文件或路径。

    5. 使用 fetch 动态加载资源(可选)

    如果上述方法仍无效,可以尝试手动加载 data.zip,并在 JS 中解压它:

    // game.js
    const fs = require('fs');
    const path = require('path');
    
    function loadZip() {
      fetch('data.zip')
        .then(res => res.arrayBuffer())
        .then(data => {
          const zip = new JSZip();
          zip.loadAsync(data).then(zip => {
            zip.forEach((relativePath, file) => {
              file.async('blob').then(blob => {
                // 将文件写入虚拟文件系统
                FS.createDataFile('/', relativePath, blob, true, true);
              });
            });
          });
        });
    }
    
    // 在 Game 初始化前调用
    loadZip();
    

    注意:这段代码需要配合 JSZip 库使用,并且要确保在 Emscripten 的 JS 中引入。


    🛠️ 总结

    | 步骤 | 内容 | |------|------| | 1 | 确认 data.bin 是否为 ZIP 文件,必要时重命名 | | 2 | 使用 --preload-file=data.zip:/ 重新编译 | | 3 | 确保 data.zipgame.js 在同一目录 | | 4 | 检查浏览器控制台错误信息 | | 5 | 如需动态加载,可使用 fetch + JSZip 方式加载 ZIP 文件 |


    💡 建议

    • 如果你是第一次使用 Emscripten 移植游戏,建议参考官方文档: https://emscripten.org/docs/compiling/Compiling.html
    • 如果你希望更灵活地管理资源,可以使用 Emscripten 的 File System API,例如:
      FILE *fp = fopen("/data/somefile.dat", "rb");
      

    如有更多细节(比如你使用的 Emscripten 版本、源码结构、报错截图等),我可以进一步帮你调试!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月5日
  • 已采纳回答 8月5日
  • 创建了问题 8月5日