CoreFileKit 本地文件操作,小白也能看懂的文件工具
做鸿蒙开发几乎都会遇到本地文件需求:保存用户输入的文本、缓存下载的图片、导出日志、记录本地数据……很多新手一上来就被「沙箱目录」「文件URI」「权限申请」绕晕,要么写的代码报权限错误,要么存完文件找不到在哪。
在鸿蒙 7(API 26)的 @kit 体系中,CoreFileKit 是官方统一的文件操作套件,替代了旧版零散的 @ohos.file.fs、@ohos.file.fileuri 等模块,API 更规整,沙箱安全机制更清晰,新手也能快速上手。
本文从最基础的沙箱概念讲起,覆盖常用文件操作,附带完整可运行的简易文件工具箱 Demo,小白照着做也能轻松实现本地文件读写。
一、先搞懂基础:沙箱、目录与 CoreFileKit
1.1 什么是 CoreFileKit
@kit.CoreFileKit 是鸿蒙系统原生文件操作能力的统一套件,涵盖文件读写、目录管理、路径与 URI 转换、文件信息查询等全部基础能力,是所有本地文件操作的官方入口。
它解决了旧版的几个痛点:
- 模块分散,文件、URI、权限分属不同包,导入繁琐
- 沙箱规则不清晰,新手容易踩权限坑
- API 命名不统一,同步异步方法混淆
1.2 小白必懂:应用沙箱是什么
这是文件操作最核心的概念,搞懂了能避开 80% 的报错。
每个鸿蒙应用都有一个独立的「私有沙箱目录」,就像应用自己的专属抽屉:
- ✅ 应用可以随便读写,不需要申请任何权限
- ❌ 其他应用无法直接访问,保证数据安全
- ✅ 应用卸载时,沙箱里的文件会一起被清理
除了私有沙箱,还有系统公共目录(相册、下载、文档等),相当于公共储物柜:
- ❌ 不能直接随便读写,必须申请对应权限
- ✅ 所有应用都可以按规则访问
- ✅ 卸载应用不会被删除
新手入门建议:先只操作应用沙箱内的文件,不用碰权限,代码写起来最简单,不容易报错。
1.3 常用沙箱目录说明
通过应用上下文可以直接获取系统分配的标准目录,千万不要自己硬编码路径,不同设备路径可能不一样。
| 目录 | 获取方式 | 用途说明 |
|---|---|---|
| 持久文件目录 | context.filesDir |
长期保存的重要数据,不会自动清理 |
| 缓存目录 | context.cacheDir |
临时缓存文件,系统存储空间不足时可能被清理 |
| 临时文件目录 | context.tempDir |
非常短生命周期的临时文件 |
示例:
const context = getContext(this);
console.info(`沙箱文件目录: ${context.filesDir}`);
1.4 版本与导入
- 最低支持版本:API 12,API 26 能力最完善
- 导入方式:
import { fs, fileUri } from '@kit.CoreFileKit';
fs:负责文件读写、目录管理等核心操作fileUri:负责文件路径与系统 URI 互相转换,分享文件时必用
二、核心 API 速查:80% 场景常用的文件操作
日常开发绝大多数场景,只需要掌握下面这几组方法就够了,全部以同步方法为例,写法最简单,适合小白入门。
2.1 最常用:文本文件读写
写入文本
import { fs } from '@kit.CoreFileKit';
const context = getContext(this);
const filePath = `${context.filesDir}/note.txt`;
// 写入文本,文件不存在会自动创建,已存在会覆盖
fs.writeText(filePath, '这是我保存的第一条笔记内容');
读取文本
// 读取文本内容
const content = fs.readText(filePath);
console.info(`读取到的内容:${content}`);
2.2 目录操作:创建、列出文件
创建目录
const dirPath = `${context.filesDir}/my_folder`;
// 创建目录,已存在不会报错
fs.mkdir(dirPath);
列出目录下所有文件
// 获取目录下所有文件名数组
const fileList = fs.listFile(context.filesDir);
console.info(`目录下的文件:${JSON.stringify(fileList)}`);
2.3 文件管理:删除、判断存在、重命名
判断文件/目录是否存在
const isExist = fs.exists(filePath);
console.info(`文件是否存在:${isExist}`);
删除文件/目录
// 删除文件
fs.delete(filePath);
// 删除目录(目录必须为空才能删除)
fs.delete(dirPath);
重命名/移动文件
// 重命名
fs.rename(filePath, `${context.filesDir}/new_note.txt`);
2.4 关键能力:文件路径与 URI 互转
这是新手最容易忽略的一步:应用沙箱的本地路径,不能直接传给其他应用/系统分享使用,必须转换成标准 File URI。
最典型的场景就是 ShareKit 分享文件,必须转 URI 才能正常分享。
import { fileUri } from '@kit.CoreFileKit';
const filePath = `${context.filesDir}/note.txt`;
// 本地路径 → 系统可识别的 File URI
const uri = fileUri.getUriFromFilePath(filePath);
console.info(`转换后的URI:${uri}`);
// URI → 本地路径(反向转换)
const path = fileUri.getFilePathFromUri(uri);
三、实战:手写简易本地文件工具箱
下面我们做一个完整可运行的 Demo,实现四个核心功能:
- 输入文本保存到沙箱文件
- 读取文件内容并展示
- 列出沙箱目录下所有文件
- 删除指定文件



全程只操作应用沙箱,不需要申请任何权限,代码复制到 Index.ets 就能直接运行。
import { fs, fileUri } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG = 'FileToolDemo';
@Entry
@Component
struct FileToolPage {
@State inputText: string = '';
@State showContent: string = '';
@State fileList: string[] = [];
// 统一文件名
private readonly demoFileName = 'demo_note.txt';
aboutToAppear() {
// 进入页面先刷新文件列表
this.refreshFileList();
}
/**
* 1. 保存文本到文件
*/
saveToFile() {
if (!this.inputText.trim()) {
promptAction.showToast({ message: '请输入内容' });
return;
}
try {
const context = getContext(this);
const filePath = `${context.filesDir}/${this.demoFileName}`;
// 写入文本
fs.writeText(filePath, this.inputText);
hilog.info(0x0000, TAG, `文件已保存:${filePath}`);
promptAction.showToast({ message: '保存成功' });
this.refreshFileList();
} catch (err) {
hilog.error(0x0000, TAG, `保存失败:${JSON.stringify(err)}`);
promptAction.showToast({ message: '保存失败' });
}
}
/**
* 2. 读取文件内容
*/
readFromFile() {
try {
const context = getContext(this);
const filePath = `${context.filesDir}/${this.demoFileName}`;
if (!fs.exists(filePath)) {
promptAction.showToast({ message: '文件不存在,请先保存' });
return;
}
this.showContent = fs.readText(filePath);
promptAction.showToast({ message: '读取成功' });
} catch (err) {
hilog.error(0x0000, TAG, `读取失败:${JSON.stringify(err)}`);
promptAction.showToast({ message: '读取失败' });
}
}
/**
* 3. 刷新文件列表
*/
refreshFileList() {
try {
const context = getContext(this);
// 列出 filesDir 下所有文件
this.fileList = fs.listFile(context.filesDir);
} catch (err) {
hilog.error(0x0000, TAG, `获取列表失败:${JSON.stringify(err)}`);
}
}
/**
* 4. 删除指定文件
*/
deleteFile(fileName: string) {
try {
const context = getContext(this);
const filePath = `${context.filesDir}/${fileName}`;
fs.delete(filePath);
promptAction.showToast({ message: '已删除' });
this.refreshFileList();
// 如果删的是演示文件,清空显示内容
if (fileName === this.demoFileName) {
this.showContent = '';
}
} catch (err) {
hilog.error(0x0000, TAG, `删除失败:${JSON.stringify(err)}`);
promptAction.showToast({ message: '删除失败' });
}
}
build() {
Column({ space: 20 }) {
Text('简易文件工具箱')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.width('90%')
.margin({ top: 40 });
// 输入区
Column({ space: 10 }) {
Text('输入保存内容')
.fontSize(16)
.width('100%');
TextArea({ text: this.inputText, placeholder: '请输入要保存的文本' })
.width('100%')
.height(120)
.borderRadius(10)
.padding(12)
.backgroundColor('#F5F5F5')
.onChange((val) => {
this.inputText = val;
});
Row({ space: 12 }) {
Button('保存到文件')
.layoutWeight(1)
.height(44)
.borderRadius(22)
.backgroundColor('#0A59F7')
.onClick(() => this.saveToFile());
Button('读取文件')
.layoutWeight(1)
.height(44)
.borderRadius(22)
.backgroundColor('#00B578')
.onClick(() => this.readFromFile());
}
.width('100%');
}
.width('90%')
.alignItems(HorizontalAlign.Start);
// 读取结果展示
if (this.showContent) {
Column({ space: 8 }) {
Text('读取到的文件内容')
.fontSize(16)
.width('100%');
Text(this.showContent)
.width('100%')
.padding(12)
.backgroundColor('#F0F7FF')
.borderRadius(8)
.fontSize(14)
.fontColor('#333333');
}
.width('90%')
.alignItems(HorizontalAlign.Start);
}
// 文件列表
Column({ space: 10 }) {
Row() {
Text('沙箱文件列表')
.fontSize(16)
.layoutWeight(1);
Text('刷新')
.fontSize(14)
.fontColor('#0A59F7')
.onClick(() => this.refreshFileList());
}
.width('100%');
if (this.fileList.length === 0) {
Text('暂无文件')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor('#AAAAAA')
.padding({ top: 20, bottom: 20 });
} else {
List({ space: 8 }) {
ForEach(this.fileList, (fileName: string) => {
ListItem() {
Row() {
Text(fileName)
.fontSize(14)
.layoutWeight(1);
Text('删除')
.fontSize(13)
.fontColor('#FF4D4F')
.onClick(() => this.deleteFile(fileName));
}
.width('100%')
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(8);
}
})
}
.width('100%');
}
}
.width('90%')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 4, color: '#1A000000' });
Blank();
Text('提示:所有文件均保存在应用私有沙箱,无需权限')
.fontSize(12)
.fontColor('#AAAAAA')
.margin({ bottom: 20 });
}
.width('100%')
.height('100%')
.backgroundColor('#F8F9FA');
}
}
运行验证步骤
- 在输入框输入任意文字,点击「保存到文件」,提示保存成功
- 点击「读取文件」,下方会展示刚才保存的内容
- 文件列表会实时显示沙箱内的所有文件
- 点击文件名右侧的删除按钮,可移除对应文件
整个 Demo 没有申请任何权限,纯沙箱内操作,不会出现权限报错,非常适合新手练手。
四、小白高频踩坑避坑指南
1. 报错:Permission denied(权限不足)
- 原因:试图访问应用沙箱以外的目录,比如直接读写系统根目录、相册目录
- 解决:新手先只操作
context.filesDir和context.cacheDir下的文件;需要访问公共目录请申请对应权限并通过系统文件选择器访问
2. 报错:No such file or directory
- 原因:文件路径写错,或者上级目录不存在
- 解决:不要自己拼接复杂路径,优先用
context.filesDir拼接;写入深层目录文件前,先用fs.mkdir创建上级目录
3. ShareKit 分享文件提示找不到文件
- 原因:直接把沙箱本地路径传给了分享接口,其他应用没有权限访问
- 解决:必须用
fileUri.getUriFromFilePath()转换成标准 File URI 再分享,系统会自动授予临时读权限
4. 读取大文件界面卡顿
- 原因:在主线程用同步方法读取大文件,阻塞了 UI 渲染
- 解决:几 KB 的小文本用同步方法没问题;几 MB 以上的大文件建议用异步方法(
fs.writeText不加 Sync 后缀的版本),配合 async/await 使用
5. 导入 @kit.CoreFileKit 报错
- 原因:SDK 版本低于 API 12,或使用了 OpenHarmony SDK
- 解决:升级 SDK 到 26.0.0 及以上,确认工程 runtimeOS 为 HarmonyOS
五、旧版 @ohos.file.fs 迁移对照表
如果你的项目还在用旧版文件接口,迁移到 CoreFileKit 非常简单,核心 API 几乎一致,只改导入即可。
| 操作 | 旧版 @ohos.file.fs | 新版 @kit.CoreFileKit |
|---|---|---|
| 导入 | import fs from '@ohos.file.fs' |
import { fs } from '@kit.CoreFileKit' |
| 写文本 | fs.writeText(path, content) |
fs.writeText(path, content) |
| 读文本 | fs.readText(path) |
fs.readText(path) |
| 列目录 | fs.listFile(path) |
fs.listFile(path) |
| 删除 | fs.delete(path) |
fs.delete(path) |
| 判断存在 | fs.exists(path) |
fs.exists(path) |
注意:旧版部分方法名有细微差异,迁移时建议对照官方文档核对,优先使用同步方法保持简单。
六、总结
CoreFileKit 是鸿蒙本地文件操作的基础入口,新手入门记住三个关键点就够了:
- 先玩沙箱:私有目录随便读写,不用权限,报错最少
- 路径别硬编:用
context.filesDir拼接,兼容性最好 - 分享转 URI:给其他应用传文件,必须走
fileUri转换
掌握本文的基础读写、目录管理、删除操作,就能覆盖 80% 的日常文件需求;后续进阶可以再学习二进制文件读写、大文件流式处理、跨应用文件共享等能力。
更多推荐



所有评论(0)