WASM平台fopen无法读取本地文件,求无需--preload-file的解决方案
问题描述
我用emcc编译了以下C代码:
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { if(argc > 2 || argc < 2) { printf("\nEnter the name of file \n"); return 0; } FILE *file = NULL; // Open file in read mode printf("file name: %s",argv[1]); file = fopen(argv[1], "r"); if(file != NULL) { printf("\nFile is successfully open\n"); } else { printf("\nFile is not opening\n"); return 0; } fclose(file); return 0; }
直接编译运行:
$emcc mycode.c $node mycode.js input.txt
输出:
file name: input.txt File is not opening
用--preload-file编译可以成功:
$emcc mycode.c --preload-file input.txt -o mycode.html $node mycode.js input.txt
输出:
file name: input.txt File is successfully open
但我不想在编译时指定文件名,希望能直接通过fopen读取本地文件系统中的文件,请问有什么方法?
解决方案
Emscripten默认使用内存文件系统(MEMFS),无法直接访问本地文件系统。要实现动态读取本地文件,需要启用NODEFS(Node.js文件系统)挂载本地目录,具体步骤如下:
1. 修改C代码,初始化NODEFS挂载
引入<emscripten.h>,通过EM_ASM宏将本地目录挂载到Emscripten的虚拟文件系统中:
#include <stdio.h> #include <string.h> #include <emscripten.h> int main(int argc, char *argv[]) { if(argc != 2) { printf("\nEnter the name of file \n"); return 0; } // 挂载当前本地目录到Emscripten文件系统的/local路径下 EM_ASM( FS.mkdir('/local'); FS.mount(NODEFS, { root: '.' }, '/local'); ); FILE *file = NULL; printf("file name: %s\n", argv[1]); // 拼接挂载路径,访问本地文件 char local_path[256]; snprintf(local_path, sizeof(local_path), "/local/%s", argv[1]); file = fopen(local_path, "r"); if(file != NULL) { printf("File is successfully open\n"); fclose(file); } else { printf("File is not opening\n"); return 0; } return 0; }
2. 编译时启用NODEFS
编译时添加-s NODERAWFS=1选项,允许Emscripten调用Node.js的原生文件系统API:
emcc mycode.c -s NODERAWFS=1 -o mycode.js
3. 运行代码
直接用Node.js运行,传入本地文件名即可:
node mycode.js input.txt
补充说明
NODEFS仅适用于Node.js环境,浏览器环境无法直接访问本地文件系统- 可以修改
FS.mount中的root参数指定任意本地目录(比如/home/user/docs) - 如果想直接用文件名而不用拼接路径,可将本地目录挂载到Emscripten虚拟文件系统的根目录:
之后直接用FS.mount(NODEFS, { root: '.' }, '/');fopen(argv[1], "r")就能访问本地文件
内容的提问来源于stack exchange,提问作者Kiran Pawar
相关产品推荐
相关产品推荐

