《HarmonyOS技术精讲-Core File Kit》第2篇:文件基础操作——创建、删除与重命名

这个功能解决什么问题
HarmonyOS NEXT 的文件操作,看似很简单,就三个 API。但很多开发者在第一次接触 fileManager.create、fileManager.delete 和 fileManager.rename 时,容易忽略一个关键点:同步与异步的选择。
这个问题不搞清楚,代码在真机上跑起来,可能会遇到应用无响应(ANR),或者回调结果与预期不符。
Core File Kit 提供了文件基础服务,它的核心定位是统一管理应用沙箱内的文件。它适合的场景包括:
- 应用数据缓存文件的管理
- 下载资源的临时存储与清理
- 用户配置文件的持久化
不适合的场景:
- 跨应用文件共享(那是
File Sharing Kit的活) - 大文件的高性能流式读写(那个需要
FileIO)
同步 vs 异步:怎么选
| 调性 | 同步调用 | 异步调用 |
|---|---|---|
| 适用场景 | 小文件、关键路径、简单操作 | 大文件、用户交互频繁、耗时操作 |
| 调用方式 | 直接返回结果 | 回调或 Promise |
| 风险 | 阻塞主线程,ANR | 回调地狱,需注意生命周期 |
实际项目里,我推荐优先用异步。同步虽然写起来方便,但文件操作如果卡住,整个 UI 线程都会冻住。哪怕只是创建一个空文件,在文件系统繁忙时,也可能会产生几十毫秒的延迟。
环境说明
DevEco Studio 版本:DevEco Studio 6.1.0 及以上
HarmonyOS SDK 版本:HarmonyOS 6.1.0(23) 及以上
目标设备:手机/平板
核心实现
1. 创建空文件
这一步比较简单,但有个坑:文件路径必须已存在。
import { fileManager } from '@kit.CoreFileKit';
let context = getContext(this);
let sandboxDir = context.filesDir;
let filePath = sandboxDir + '/demo.txt';
// 同步创建
try {
let file = fileManager.createSync(filePath);
console.info('create file success' + file.name);
} catch (err) {
console.error('create file fail' + err.message);
}
// 异步创建
fileManager.create(filePath).then((file) => {
console.info('create file success' + file.name);
}).catch((err) => {
console.error('create file fail' + err.message);
});
2. 删除指定文件
删除操作没有回收站,一旦执行,数据就没了。
// 同步删除
try {
fileManager.deleteSync(filePath);
console.info('delete file success');
} catch (err) {
console.error('delete file fail' + err.message);
}
// 异步删除
fileManager.delete(filePath).then(() => {
console.info('delete file success');
}).catch((err) => {
console.error('delete file fail' + err.message);
});
3. 重命名文件
重命名涉及目标路径,如果目标路径已有文件会直接覆盖。
let newPath = sandboxDir + '/new_demo.txt';
// 同步重命名
try {
fileManager.renameSync(filePath, newPath);
console.info('rename file success');
} catch (err) {
console.error('rename file fail' + err.message);
}
// 异步重命名
fileManager.rename(filePath, newPath).then(() => {
console.info('rename file success');
}).catch((err) => {
console.error('rename file fail' + err.message);
});
这里需要注意:rename 只能在同一文件系统内移动。跨沙箱目录重命名会失败。
常见问题
问题1:权限申请后,文件操作仍然失败
现象:调用了 requestPermission,应用有读写权限,但 create 返回错误码 13900001。
原因:HarmonyOS 的文件权限分两个层级:应用沙箱内权限和沙箱外权限。Core File Kit 的 create 等 API 只在应用沙箱内工作,不需要单独申请 fileManager.Permission。如果你误申请了沙箱外权限,反而可能引起生命周期冲突。
解法:Core File Kit 的文件操作不需要任何运行时权限申请。沙箱路径天然可读写。如果你用到沙箱外路径(如 download/ 目录),才需要额外权限。
问题2:异步回调中的 UI 状态同步
现象:异步删除文件成功后,页面列表没有更新。
原因:异步回调在非 UI 线程执行,直接修改 @State 变量不会触发刷新。
解法:在回调里通过 @Watch 或 wrapped callback 通知 UI 线程。
@State fileList: string[] = [];
onDeleteFile(path: string) {
fileManager.delete(path).then(() => {
// 必须在主线程修改状态
this.fileList = this.fileList.filter(f => f !== path);
}).catch((err) => {
console.error('delete fail' + err.message);
});
}
最佳实践
-
不要在
build()函数中直接调用文件操作。build()会频繁触发,每次创建一个新的文件流会导致内存泄漏。建议在aboutToAppear()或按钮事件中触发。 -
创建文件前先检查目录是否存在。
createSync不会自动创建父目录。如果父目录不存在,会直接报错。建议用accessSync先检查。 -
异步链式调用优先于嵌套。多步文件操作(创建 -> 写入 -> 删除)推荐用 Promise 链,避免回调嵌套。
Demo 入口
@Entry
@Component
struct FileDemoPage {
@State fileName: string = 'test.txt';
@State log: string = '';
build() {
Column() {
Button('同步创建文件')
.onClick(() => {
this.syncCreate();
})
Button('异步删除文件')
.onClick(() => {
this.asyncDelete();
})
Text(this.log)
.fontSize(14)
}
.padding(20)
}
syncCreate() {
let context = getContext(this);
let filePath = context.filesDir + '/' + this.fileName;
try {
fileManager.createSync(filePath);
this.log = '创建成功';
} catch (err) {
this.log = '创建失败: ' + err.message;
}
}
asyncDelete() {
let context = getContext(this);
let filePath = context.filesDir + '/' + this.fileName;
fileManager.delete(filePath).then(() => {
this.log = '删除成功';
}).catch((err) => {
this.log = '删除失败: ' + err.message;
});
}
}
FAQ
Q:为什么真机能创建文件,模拟器返回 -1?
A:模拟器的文件系统路径与真机不同。filesDir 在模拟器上可能指向一个只读路径。建议在真机上测试文件写入功能。
Q:为什么重命名后,原始文件还存在?
A:检查一下目标路径是否写了完整路径。rename 相当于移动+重命名。如果目标路径为空或错误,文件会留在原地。
Q:删除大文件后,磁盘空间没有立即释放?
A:HarmonyOS 文件系统对删除操作采用延迟回收机制。空间会在系统低峰期回收,几秒内不会看到空间增加。这是正常行为。
示例代码地址:项目地址
更多推荐


所有评论(0)