查看: 167|回复: 0

鸿蒙 ASCF 文件 API 避坑:internal 路径与编

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
文件操作是鸿蒙元服务开发绕不开的一环:缓存数据、保存图片、读取配置、解压文件都会用到。ASCF 的文件能力通过 has.getFileSystemManager() 暴露为 FileSystemManager,且是全局唯一单例,设计上与 RecorderManager、BackgroundAudioManager 类似。使用前先记两条硬规则:所有文件 API 的路径只支持 internal:// 开头的沙箱路径,不支持外部存储路径;相册等外部路径不能直接操作,通常要先 copyFile 到沙箱。

一、获取实例与路径规则
  1. const fs = has.getFileSystemManager();
复制代码
路径只支持 internal://,这是后续所有读写、目录、解压操作的前提。

二、基础文件读写
写文件最常用的是 writeFile,data 支持 string 和 ArrayBuffer。写字符串可直接指定 encoding:
  1. const fs = has.getFileSystemManager();
  2. fs.writeFile({
  3.   filePath: 'internal://cache/data.txt',
  4.   data: 'Hello World',
  5.   encoding: 'utf-8',
  6.   success: () => {
  7.     console.info('写入成功');
  8.   },
  9.   fail: (err) => {
  10.     console.error('写入失败:', err);
  11.   }
  12. });
复制代码
同步写法用 writeFileSync。读文件用 readFile:传 encoding: 'utf-8' 返回字符串;不传 encoding 返回 ArrayBuffer。删除文件用 unlink;检查存在用 access;拷贝用 copyFile;重命名用 rename。
  1. fs.readFile({
  2.   filePath: 'internal://cache/data.txt',
  3.   encoding: 'utf-8',
  4.   position: 0,
  5.   success: (res) => {
  6.     console.info('文件内容:', res.data);
  7.   },
  8.   fail: (err) => {
  9.     console.error('读取失败:', err);
  10.   }
  11. });
  12. fs.unlink({
  13.   filePath: 'internal://cache/data.txt',
  14.   success: () => {
  15.     console.info('删除成功');
  16.   }
  17. });
  18. fs.copyFile({
  19.   srcPath: 'internal://cache/temp.txt',
  20.   destPath: 'internal://files/saved.txt',
  21.   success: () => {
  22.     console.info('拷贝成功');
  23.   }
  24. });
复制代码
追加写入用 appendFile,适合日志,不用先读再拼接:
  1. fs.appendFile({
  2.   filePath: 'internal://cache/log.txt',
  3.   data: '新的一行\n',
  4.   encoding: 'utf-8',
  5.   success: () => {
  6.     console.info('追加成功');
  7.   }
  8. });
复制代码
截断文件用 truncate,length 指定保留的字节数。

三、目录与文件信息
创建目录用 mkdir,recursive: true 可递归创建中间目录,类似 mkdir -p;读取目录用 readdir,返回 res.files;删除目录用 rmdir,recursive: true 会删除目录下所有文件和子目录。
  1. fs.mkdir({
  2.   dirPath: 'internal://cache/mydir',
  3.   recursive: true,
  4.   success: () => {
  5.     console.info('目录创建成功');
  6.   }
  7. });
  8. fs.readdir({
  9.   dirPath: 'internal://cache/',
  10.   success: (res) => {
  11.     console.info('目录内容:', res.files);
  12.   }
  13. });
复制代码
获取文件大小用 getFileInfo,获取文件状态用 stat,Stats 对象提供 isFile() 和 isDirectory()。getSavedFileList 只列出通过 saveFile 保存的文件,包含 filePath、size、createTime,不包括 writeFile 创建的文件;要列出所有文件应使用 readdir。

四、高级 fd 读写、解压与文档预览
如果要精确控制读写位置或处理大文件,可以用文件描述符方式:openSync 打开,readSync 读取,writeSync 写入,closeSync 关闭。示例中 flag 使用 'r+' 表示读写模式。
  1. const fs = has.getFileSystemManager();
  2. const fd = fs.openSync({
  3.   filePath: 'internal://cache/data.bin',
  4.   flag: 'r+'
  5. });
  6. const readResult = fs.readSync({
  7.   fd: fd,
  8.   arrayBuffer: new ArrayBuffer(1024),
  9.   length: 1024
  10. });
  11. console.info('读取了', readResult.bytesRead, '字节');
  12. fs.writeSync({
  13.   fd: fd,
  14.   data: '写入的数据',
  15.   encoding: 'utf-8'
  16. });
  17. 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/ 下的沙箱持久化目录。
  1. has.chooseFile({
  2.   type: 'file',
  3.   count: 1,
  4.   success: (res) => {
  5.     const file = res.tempFiles[0];
  6.     const fs = has.getFileSystemManager();
  7.     const destPath = `internal://files/${file.name}`;
  8.     fs.copyFile({
  9.       srcPath: file.path,
  10.       destPath: destPath,
  11.       success: () => {
  12.         console.info('文件已保存:', destPath);
  13.       }
  14.     });
  15.   }
  16. });
复制代码

六、踩坑清单
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 的区别记住,基本就能避开主要问题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-17 13:18 , Processed in 0.025294 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部