HarmonyOS文件基础服务(Core File Kit)实战演练03-文件增删改查与目录操作
在应用开发中,文件管理是最基础且高频的操作。无论是缓存用户数据、保存下载文件,还是处理日志输出,都离不开文件的增删改查。HarmonyOS 的 Core File Kit 提供了完整的文件与目录操作能力,但很多开发者容易忽视沙箱路径限制和异步处理的注意事项。本文基于 API Version 6.1.0(23) 的官方文档,整理应用沙箱内文件管理的核心用法,涵盖创建、删除、复制、移动、重命名、属性获取及目录遍历。
核心概念
Core File Kit 提供的接口遵循 同步/异步 两种调用风格,所有文件操作均限制在应用的 沙箱目录 内。操作前需通过 getContext().filesDir 等方式获取应用私有目录路径。文档中明确提到:"文件路径必须为应用沙箱路径",否则操作失败。

环境准备
本文示例基于 DevEco Studio 6.1.0 Release、HarmonyOS SDK 6.1.0(23) 版本,API 版本 23。需引入 @kit.CoreFileKit(文档中未出现具体 import 路径,但建议按标准方式导入)。
核心实现
所有文件操作均需在 aboutToAppear 或用户交互回调中执行,使用 async/await 处理异步逻辑。注意:同步方法会阻塞 UI 线程,生产环境请优先使用异步版本。
1. 创建文件
typescript
import { fileIo } from '@kit.CoreFileKit';
async function createFile(filePath: string) {
try {
const file = await fileIo.open(filePath, fileIo.OpenMode.CREATE);
await fileIo.close(file);
console.info('文件创建成功');
} catch (err) {
console.error(`创建失败: ${err.code}, ${err.message}`);
}
}
OpenMode.CREATE 表示若文件不存在则创建,存在则直接打开。如果希望追加内容而非覆盖,可以使用 OpenMode.APPEND。
2. 删除文件
typescript
async function deleteFile(filePath: string) {
try {
await fileIo.unlink(filePath);
console.info('文件已删除');
} catch (err) {
console.error(`删除失败: ${err.code}, ${err.message}`);
}
}
unlink 仅适用于文件,若传入目录路径会抛出错误。删除前建议检查文件是否存在,避免不必要的异常。
3. 复制与移动
typescript
async function copyFile(src: string, dest: string) {
try {
await fileIo.copyFile(src, dest);
console.info('文件复制完成');
} catch (err) {
console.error(`复制失败: ${err.code}, ${err.message}`);
}
}
async function moveFile(src: string, dest: string) {
try {
await fileIo.moveFile(src, dest);
console.info('文件移动成功');
} catch (err) {
console.error(`移动失败: ${err.code}, ${err.message}`);
}
}
注意 :moveFile 会删除原文件。若目标路径已存在,moveFile 会抛出异常(文档未明确说明覆盖行为,实际测试中不会自动覆盖)。如需覆盖,需先调用 unlink 删除目标文件后再执行移动。
4. 重命名
typescript
async function renameFile(oldPath: string, newPath: string) {
try {
await fileIo.rename(oldPath, newPath);
console.info('文件重命名成功');
} catch (err) {
console.error(`重命名失败: ${err.code}, ${err.message}`);
}
}
rename 同样适用于目录。注意新路径必须与旧路径在同一个文件系统中(通常都在沙箱内),否则可能失败。推荐使用绝对路径而非相对路径。
5. 获取文件属性
typescript
async function getFileInfo(filePath: string) {
try {
const stat = await fileIo.stat(filePath);
console.info(`大小: ${stat.size}, 修改时间: ${stat.mtime}, 是否目录: ${stat.isDirectory()}`);
return stat;
} catch (err) {
console.error(`获取属性失败: ${err.code}, ${err.message}`);
return null;
}
}
fileIo.stat 返回 Stat 对象,包含 size、mtime、ctime、isDirectory() 等方法。注意 mtime 是 Unix 时间戳(毫秒),如需格式化需自行转换。
6. 目录操作
创建目录:
typescript
async function createDir(dirPath: string) {
try {
await fileIo.mkdir(dirPath, true); // recursive: true 会递归创建父目录
console.info('目录创建成功');
} catch (err) {
console.error(`创建目录失败: ${err.code}, ${err.message}`);
}
}
读取目录列表:
typescript
async function listDir(dirPath: string) {
try {
const files = await fileIo.listFile(dirPath);
console.info(`目录内容: ${JSON.stringify(files)}`);
// files 是 string[],每个元素是文件名(不含路径)
} catch (err) {
console.error(`读取目录失败: ${err.code}, ${err.message}`);
}
}
删除目录(空目录):
typescript
async function removeDir(dirPath: string) {
try {
await fileIo.rmdir(dirPath);
console.info('空目录删除成功');
} catch (err) {
console.error(`删除目录失败: ${err.code}, ${err.message}`);
}
}
rmdir 只能删除空目录。如需删除非空目录,需要先遍历删除所有子文件和子目录(递归实现)。官方推荐使用 fileIo.remove(部分版本可能不支持),否则需自行编写递归逻辑。
常见误区与注意事项
- 路径必须以沙箱路径开头,例如
getContext().filesDir + "/test.txt"。使用sandboxPath函数可校验路径合法性。 - 异步方法需要
await,但记得在外层try-catch,因为文件操作可能因权限、磁盘满等原因失败。 - 频繁创建/删除文件会消耗 IO,建议在后台线程执行批量操作,避免阻塞 UI 响应。
实际开发中,文件操作往往与缓存清理、数据导入导出等业务结合。你是否在项目中遇到过跨沙箱路径访问的坑?欢迎在评论区分享你的踩坑经历。
处理文件时,经常需要对文件重命名、获取属性或管理目录。HarmonyOS 的 fileIo 模块提供了这些操作的同步和异步接口,本文直接给出常用操作的完整代码,便于复制到项目中。
5. 获取文件属性
typescript
async function getFileStat(filePath: string) {
try {
const stat = await fileIo.stat(filePath);
console.info(`大小: ${stat.size}, 最后修改时间: ${stat.mtime}`);
} catch (err) {
console.error(`获取属性失败: ${err.code}, ${err.message}`);
}
}
stat 对象的属性包括 size、mtime、atime、ctime 等(具体字段参考官方文档)。注意 :mtime 是时间戳,建议转换为 Date 对象以便展示。
6. 目录操作
创建目录
typescript
async function createDir(dirPath: string) {
try {
await fileIo.mkdir(dirPath);
console.info('目录创建成功');
} catch (err) {
console.error(`目录创建失败: ${err.code}, ${err.message}`);
}
}
删除目录
typescript
async function removeDir(dirPath: string) {
try {
await fileIo.rmdir(dirPath);
console.info('目录已删除');
} catch (err) {
console.error(`目录删除失败: ${err.code}, ${err.message}`);
}
}
限制 :rmdir 只能删除空目录,非空需先遍历删除子项。如果目录下有文件,可以先用 listFile 递归删除。
目录遍历
typescript
async function listDir(dirPath: string) {
try {
const files = await fileIo.listFile(dirPath);
for (const file of files) {
console.info(`文件名: ${file.name}, 类型: ${file.isDirectory ? '目录' : '文件'}`);
}
} catch (err) {
console.error(`遍历失败: ${err.code}, ${err.message}`);
}
}
注意事项
- 所有文件路径必须为应用沙箱路径(如
getContext().filesDir),非沙箱路径操作会抛出权限错误。 - 异步操作建议使用
try/catch捕获错误,错误对象包含code和message字段,便于定位问题。 - 目录删除前需确保目录为空,否则操作失败。可以先调用
listFile检查子项数量。 copyFile和moveFile的目标路径若已存在同名文件,行为取决于平台具体实现(文档未明确说明覆盖策略),建议操作前检查目标是否存在。可以用stat判断文件是否存在,再决定是否先删除或重命名。
常见问题 FAQ
Q: 操作时提示"路径不在沙箱内"怎么办?
A: 确认传入的路径是由 getContext().filesDir、getContext().cacheDir 等沙箱路径拼接而来,而不是硬编码的系统路径。例如:${getContext().filesDir}/data.txt。
Q: 目录遍历返回的结果不包含子目录内容?
A: listFile 仅返回直接子项,需递归调用以遍历多级目录。可以在循环中判断 file.isDirectory 再递归执行 listFile。
上一篇 介绍了文件基础服务的引入与环境配置,下一篇将深入文件读写操作与流式处理。如果你在实际使用中遇到其他问题,欢迎留言交流。