参考官网文档 Using files
首先,对于webassembly而言,无法直接访问本地文件(即使是通过C/C++代码)。但是emscripten提供了File System Overview,可以在编译时将本地文件预加载到输出文件中,使得输出文件可以访问,具体步骤如下:
一、C代码
#include <stdio.h>
int main() {
FILE *file = fopen("test.txt", "rb");
if (!file) {
printf("cannot open file\n");
return 1;
}
while (!feof(file)) {
char c = fgetc(file);
if (c != EOF) {
putchar(c);
}
}
fclose (file);
return 0;
}
命名为fileopt.c,并在同目录下创建test.txt文本文件,在其内保存一段文字。
二、编译
emcc -sEXIT_RUNTIME -o fileopt.html fileopt.c --preload-file test.txt
其中EXIT_RUNTIME是为了确保文件流刷新,如果没有会有如下警告:
stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.
并且,输出内容不全。
编译完成后,本地会出现一个同名的*.data文件,这里面打包了所有的预置文件内容,当然我们也可以自己手动打包文件,参考Packaging Files。
三、运行
双击运行。如果有同源策略问题(跨域问题)参考:html的同源策略问题
四、C++ example
代码
#include <iostream>
#include <fstream>
#include <filesystem>
using namespace std;
int main() {
ifstream fin;
fin.open("test.txt",ios::in);
if(fin.is_open()){
string s;
while(getline(fin,s)){
cout << s <<endl;
}
fin.close();
}
else{
cout << "test.txt open failed" <<endl;
}
return 0;
}
命令
emcc -sEXIT_RUNTIME -o fileopt.html fileopt.cpp --preload-file test.txt
五、扩展
如果每次都需要编译才能加载本地文件,那么易用性就会比较差。
但是首先对于单文件而言,直接替换*.data的内容即可生效;此外上面也提到可以通过package file的方式单独打包文件(待后续研究),所以还是比较方便的。