文件操作是鸿蒙元服务开发绕不开的一环:缓存数据、保存图片、读取配置、解压文件都会用到。ASCF 的文件能力通过 has.getFileSystemManager() 暴露为 FileSystemManager,且是全局唯一单例,设计上与 RecorderManager、BackgroundAudioManager 类似。使用前先记两条硬规则:所有文件 API 的路径只支持 internal:// 开头的沙箱路径,不支持外部存储路径;相册等外部路径不能直接操作,通常要先 copyFile 到沙箱。
一、获取实例与路径规则- const fs = has.getFileSystemManager();
复制代码 路径只支持 internal://,这是后续所有读写、目录、解压操作的前提。
二、基础文件读写
写文件最常用的是 writeFile,data 支持 string 和 ArrayBuffer。写字符串可直接指定 encoding:- const fs = has.getFileSystemManager();
- fs.writeFile({
- filePath: 'internal://cache/data.txt',
- data: 'Hello World',
- encoding: 'utf-8',
- success: () => {
- console.info('写入成功');
- },
- fail: (err) => {
- console.error('写入失败:', err);
- }
- });
复制代码 同步写法用 writeFileSync。读文件用 readFile:传 encoding: 'utf-8' 返回字符串;不传 encoding 返回 ArrayBuffer。删除文件用 unlink;检查存在用 access;拷贝用 copyFile;重命名用 rename。- fs.readFile({
- filePath: 'internal://cache/data.txt',
- encoding: 'utf-8',
- position: 0,
- success: (res) => {
- console.info('文件内容:', res.data);
- },
- fail: (err) => {
- console.error('读取失败:', err);
- }
- });
- fs.unlink({
- filePath: 'internal://cache/data.txt',
- success: () => {
- console.info('删除成功');
- }
- });
- fs.copyFile({
- srcPath: 'internal://cache/temp.txt',
- destPath: 'internal://files/saved.txt',
- success: () => {
- console.info('拷贝成功');
- }
- });
复制代码 追加写入用 appendFile,适合日志,不用先读再拼接:- fs.appendFile({
- filePath: 'internal://cache/log.txt',
- data: '新的一行\n',
- encoding: 'utf-8',
- success: () => {
- console.info('追加成功');
- }
- });
复制代码 截断文件用 truncate,length 指定保留的字节数。
三、目录与文件信息
创建目录用 mkdir,recursive: true 可递归创建中间目录,类似 mkdir -p;读取目录用 readdir,返回 res.files;删除目录用 rmdir,recursive: true 会删除目录下所有文件和子目录。- fs.mkdir({
- dirPath: 'internal://cache/mydir',
- recursive: true,
- success: () => {
- console.info('目录创建成功');
- }
- });
- fs.readdir({
- dirPath: 'internal://cache/',
- success: (res) => {
- console.info('目录内容:', res.files);
- }
- });
复制代码 获取文件大小用 getFileInfo,获取文件状态用 stat,Stats 对象提供 isFile() 和 isDirectory()。getSavedFileList 只列出通过 saveFile 保存的文件,包含 filePath、size、createTime,不包括 writeFile 创建的文件;要列出所有文件应使用 readdir。
四、高级 fd 读写、解压与文档预览
如果要精确控制读写位置或处理大文件,可以用文件描述符方式:openSync 打开,readSync 读取,writeSync 写入,closeSync 关闭。示例中 flag 使用 'r+' 表示读写模式。- const fs = has.getFileSystemManager();
- const fd = fs.openSync({
- filePath: 'internal://cache/data.bin',
- flag: 'r+'
- });
- const readResult = fs.readSync({
- fd: fd,
- arrayBuffer: new ArrayBuffer(1024),
- length: 1024
- });
- console.info('读取了', readResult.bytesRead, '字节');
- fs.writeSync({
- fd: fd,
- data: '写入的数据',
- encoding: 'utf-8'
- });
- fs.closeSync({ fd: fd });
复制代码 解压用 unzip,只支持 zip 格式,不支持 tar.gz、rar 等;has.openDocument 可调起系统预览器打开文档,支持 pdf、doc、docx、xls、xlsx、ppt、pptx。
五、典型场景
缓存 JSON:写入用 writeFile,读取用 readFileSync,并处理解析异常。
日志追加:用 appendFile 写入时间戳和消息。
保存 chooseFile 文件:chooseFile 返回的临时路径不能直接读写,需要先 copyFile 到 internal://files/ 下的沙箱持久化目录。- has.chooseFile({
- type: 'file',
- count: 1,
- success: (res) => {
- const file = res.tempFiles[0];
- const fs = has.getFileSystemManager();
- const destPath = `internal://files/${file.name}`;
- fs.copyFile({
- srcPath: file.path,
- destPath: destPath,
- success: () => {
- console.info('文件已保存:', destPath);
- }
- });
- }
- });
复制代码
六、踩坑清单
1. 路径只支持 internal://,外部路径如相册路径不能直接操作,需要先 copyFile 到沙箱。
2. writeFile 默认覆盖写入,不是追加;要追加用 appendFile。
3. readFile 不传 encoding 时 res.data 是 ArrayBuffer,不是字符串;需要字符串就传 encoding: 'utf-8'。
4. 写图片、音频等二进制数据时,data 要传 ArrayBuffer,且不要传 encoding。
5. getSavedFileList 只列出 saveFile 保存的文件,不包括 writeFile 创建的文件;列出所有文件用 readdir。
6. 删文件用 unlink,删目录用 rmdir,搞反会报错。
7. unzip 只支持 zip,不支持 tar.gz、rar 等格式。
从使用频率看,日常开发最常用的是 writeFile、readFile、appendFile、unlink、copyFile、mkdir、readdir。如果只是存简单 key-value 数据,用 has.setStorage / has.getStorage 就够了,不必折腾文件 API;文件 API 更适合存大数据、二进制文件、日志这类场景。把 internal:// 路径限制、readFile 的 encoding 行为、writeFile 与 appendFile 的区别记住,基本就能避开主要问题。 |