引言

文件操作是移动应用最基础的能力之一——缓存图片需要写入临时目录,用户数据需要持久化到文件,日志需要追加写入文本。HarmonyOS NEXT 通过 @ohos.file.fs 模块将 POSIX 风格的文件系统操作封装为 JavaScript/ArkTS 友好的同步/异步 API,让开发者在应用沙箱内自由地进行目录浏览、文件读写、复制删除和属性查询。

@ohos.file.fs 属于 @kit.CoreFileKit,是应用沙箱文件系统的统一入口。它导出 fileIo 命名空间,提供 50 余个文件操作函数——从基础的 open/read/write/close 到高级的 listFile/stat/copyFile/moveFile/unlink,覆盖文件生命周期的全流程。每个函数都有同步(Sync 后缀)和异步(Promise + Callback)两种版本。

与 Android 的 java.io.File + FileInputStream(Java 风格,需要异常处理模板代码)和 iOS 的 FileManager(Foundation 框架,Objective-C 风格)不同,鸿蒙将文件 I/O 设计为模块级命名空间函数,通过 fileIo.openSync() 返回 File 句柄操作单个文件,通过 fileIo.listFileSync() 目录遍历,通过 fileIo.statSync() 查询元数据——简洁直接,无复杂的类继承体系。

本文将深入讲解 @ohos.file.fs 的目录浏览、文件读写、元数据查询和批量操作四大核心能力,并构建一个"文件系统实验室"Demo——在应用沙箱内完成文件创建、查看、复制和删除的全流程操作。

一、API 架构:命名空间 + File 句柄模式

1.1 核心设计理念

@ohos.file.fs 的设计核心是命名空间函数 + File 句柄的双层模型。导入时使用 fileIo 命名空间:

import fileIo from '@ohos.file.fs';

命名空间提供两类函数:

路径级操作(直接操作文件路径,无需 File 句柄):

  • listFileSync(path: string): string[] — 列出目录内容
  • statSync(path: string): Stat — 获取文件元数据
  • readTextSync(path: string): string — 读取文本文件全部内容
  • copyFileSync(src: string, dest: string): void — 复制文件
  • moveFileSync(src: string, dest: string): void — 移动文件
  • unlinkSync(path: string): void — 删除文件
  • accessSync(path: string): boolean — 检查文件是否可访问
  • mkdirSync(path: string): void / rmdirSync(path: string): void — 创建/删除目录

句柄级操作(需要先 openSync 获取 File 对象):

  • openSync(path: string, mode?: number): File — 打开文件返回句柄
  • writeSync(fd: number, data: string | ArrayBuffer): void — 向文件描述符写入数据
  • readSync(fd: number, buffer: ArrayBuffer, options?: object): number — 从文件描述符读取数据
  • closeSync(file: File): void — 关闭文件释放句柄

这种双层设计让简单操作可以直接走路径级 API(如整个读取小文件用 readTextSync),复杂操作走 File 句柄获得精确控制(如日志追加写入用 openSync(path, APPEND) + writeSync(fd, line) + closeSync)。

1.2 sandbox 沙箱限制

所有文件操作都限制在应用沙箱目录内:

  • getContext(this).filesDir — 应用私有文件目录(/data/storage/el2/base/haps/entry/files/)
  • getContext(this).cacheDir — 缓存目录(系统可能在空间不足时清空)
  • getContext(this).tempDir — 临时目录(应用退出后可能清空)

尝试访问沙箱外的路径会抛出权限异常。这是鸿蒙的安全模型——与 iOS 的沙箱机制类似,比 Android 的存储权限更严格。

// 合法:访问沙箱内文件
const filesDir = getContext(this).filesDir;
const content = fileIo.readTextSync(filesDir + '/note.txt');

// 非法:尝试访问沙箱外路径会抛异常
// fileIo.readTextSync('/system/etc/hosts'); // ERROR

1.3 OpenMode 打开模式常量

fileIo.OpenMode 命名空间提供文件打开模式常量,遵循 POSIX 文件权限惯例(八进制值):

常量 含义
READ_ONLY 只读 0o0
WRITE_ONLY 只写 0o1
READ_WRITE 读写 0o2
CREATE 文件不存在时创建 0o100
TRUNC 打开时清空文件 0o1000
APPEND 追加模式 0o2000

多个模式通过按位或(|)组合使用:

// 创建新文件(仅写入 + 创建 + 清空原有内容)
const file = fileIo.openSync(path,
  fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);

// 追加写入日志
const logFile = fileIo.openSync(path,
  fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.APPEND);

二、目录浏览与文件发现

2.1 listFileSync —— 列出目录内容

fileIo.listFileSync(path: string): string[] 返回目录下所有文件和子目录的名称数组。这是最简单的文件列表 API——不返回元数据,只返回名称字符串。

const filesDir = getContext(this).filesDir;
const names = fileIo.listFileSync(filesDir);
console.log('文件数量: ' + names.length.toString());
// names = ['note.txt', 'config.json', 'cache', 'download.tmp']

返回的名称只是文件名,不包含完整路径。区分文件和目录需要额外调用 statSync() 检查 mode 字段——但 Demo 中做了简化处理,因为可以通过 listFileSync 遍历到的都可能是文件或目录。

2.2 statSync —— 获取文件元数据

fileIo.statSync(path: string): Stat 返回一个 Stat 接口对象,包含文件的完整元数据:

interface Stat {
  readonly ino: bigint;    // inode 号
  readonly size: bigint;   // 文件大小(字节)
  readonly mode: number;   // 文件权限(八进制形式,如 0o644)
  readonly uid: number;    // 所有者 UID
  readonly gid: number;    // 组 ID
  readonly atime: bigint;  // 最后访问时间(毫秒时间戳)
  readonly mtime: bigint;  // 最后修改时间(毫秒时间戳)
}

其中 mode 可以用八进制格式显示给用户——Number(st.mode).toString(8) 将其转换为 "33188" 这样的八进制字符串(实际上底层是 0o100644 即普通文件 + 权限 644)。

const st = fileIo.statSync(fullPath);
const sizeMB = (Number(st.size) / (1024 * 1024)).toFixed(2) + ' MB';
const mtime = new Date(Number(st.mtime));
const perm = '0o' + Number(st.mode).toString(8);
console.log('文件大小: ' + sizeMB + ', 修改时间: ' + mtime + ', 权限: ' + perm);

sizemtimebigint 类型——需要用 Number() 转换后才能参与字符串拼接或数学运算。
在这里插入图片描述
在这里插入图片描述

三、文件读写操作

3.1 readTextSync —— 最简单的文本读取

fileIo.readTextSync(path: string): string 一次性读取整个文件并以 UTF-8 文本返回。适用于配置文件、JSON 数据和日志文件等小文件场景。

try {
  const content = fileIo.readTextSync(fullPath);
  this.fileContent = content;
  console.log('读取到 ' + content.length.toString() + ' 个字符');
} catch (e) {
  console.error('读取失败');
}

文件不存在或不可读时会抛出异常,需要 try/catch 保护。

3.2 openSync + writeSync + closeSync —— 三步写文件

创建或写入文件需要三个步骤:

// 1. 打开文件(创建 + 只写 + 清空)
const file = fileIo.openSync(fullPath,
  fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);

// 2. 写入内容
fileIo.writeSync(file.fd, 'Hello HarmonyOS!\n第二行内容');

// 3. 关闭释放
fileIo.closeSync(file);

writeSync 接受 string | ArrayBuffer 类型——写入文本直接用字符串,写入二进制数据用 ArrayBuffer

Demo 中封装了创建文件的操作:

private createFile(): void {
  const fullPath = this.currentDir + '/' + this.newFileName.trim();
  const file = fileIo.openSync(fullPath,
    fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
  fileIo.writeSync(file.fd, this.newFileContent);
  fileIo.closeSync(file);
  this.refreshFileList();
}

用户输入文件名和内容后点击"创建",文件出现在目录列表中。

四、文件复制、删除与重命名

4.1 copyFileSync —— 按路径复制

fileIo.copyFileSync(src: string, dest: string): void 直接将源文件复制到目标路径。不需要先读取内容再写入——系统内部直接使用高效的内核复制。

// 复制文件:note.txt → note_copy.txt
const srcPath = this.currentDir + '/' + name;
const destPath = this.currentDir + '/' + name.replace(/(\.[^.]+)$/, '_copy$1');
fileIo.copyFileSync(srcPath, destPath);

Demo 中在每个文件旁边放了"复制"按钮,点击后自动生成 原文件名_copy.扩展名 格式的副本。

4.2 unlinkSync —— 删除文件

fileIo.unlinkSync(path: string): void 删除指定路径的文件。注意这不是 deleteremove——POSIX 系统中删除文件的系统调用是 unlink(移除目录项到 inode 的链接)。

const fullPath = this.currentDir + '/' + name;
fileIo.unlinkSync(fullPath);

Demo 中每个文件旁边有红色"删除"按钮,点击后立即删除并刷新目录列表。

4.3 moveFileSync / renameSync —— 重命名

fileIo.moveFileSync(src: string, dest: string): void 移动或重命名文件。在同一文件系统内,移动和重命名是同一个操作(只修改目录项,不复制数据)。

// 重命名
fileIo.moveFileSync(filesDir + '/old_name.txt', filesDir + '/new_name.txt');
// 跨目录移动
fileIo.moveFileSync(filesDir + '/data.txt', cacheDir + '/data_backup.txt');

五、实战 Demo:文件系统实验室

5.1 页面设计

"文件系统实验室"页面分为五个功能区域:

  1. 快捷操作栏:"刷新列表"按钮(重新读取目录)+ "创建文件"按钮(展开/收起创建面板)

  2. 文件创建面板(可折叠):TextInput 输入文件名(默认 “note.txt”)+ TextArea 输入文件内容(默认 “Hello HarmonyOS!”)+ 绿色"创建"按钮

  3. 目录内容列表:展示当前目录下所有文件名,每个文件右侧有三个操作按钮——“查看”(蓝色)“复制”(天蓝)“删除”(红色)。目录项不显示操作按钮

  4. 文件内容查看面板(点击"查看"后展开):显示文件属性卡片(大小/修改时间/权限三列)+ 文件内容(等宽字体、灰色背景)

  5. 操作日志:记录所有操作——列目录、创建、查看、复制、删除及其结果

5.2 核心实现

状态模型设计

@State fileList: FileItem[] = [];
@State currentDir: string = '';
@State selectedFile: string = '';
@State fileContent: string = '';
@State fileSize: string = '--';
@State fileMtime: string = '--';
@State fileMode: string = '--';
@State newFileName: string = 'note.txt';
@State newFileContent: string = 'Hello HarmonyOS!';
@State showCreate: boolean = false;
@State showContent: boolean = false;
@State logs: LogEntry[] = [];

设计要点:

  • fileList 存储文件列表(名称 + 是否为目录),每次操作后通过 refreshFileList() 重新读取
  • selectedFile 记录当前查看的文件名,showContent 控制查看面板的显示/隐藏
  • showCreate 控制创建面板的展开/折叠
  • 文件属性(size/mtime/mode)只在查看文件时通过 statSync() 获取

目录列表刷新

private refreshFileList(): void {
  try {
    const files = fileIo.listFileSync(this.currentDir);
    this.fileList = [];
    for (let i = 0; i < files.length; i++) {
      try {
        const fullPath = this.currentDir + '/' + files[i];
        const st = fileIo.statSync(fullPath);
        this.fileList.push({
          name: files[i],
          isDir: (Number(st.mode) & 0o40000) !== 0
        } as FileItem);
      } catch (e) {
        this.fileList.push({ name: files[i], isDir: false } as FileItem);
      }
    }
  } catch (e) {
    this.addLog('列出目录失败', 'error');
  }
}

通过检查 mode0o40000 位来判断是否为目录——这是 POSIX 文件类型的掩码。

5.3 交互方式

Demo 提供四个核心交互点:

  1. 浏览目录:进入页面自动列出 filesDir 下的所有文件,点击"刷新列表"可重新读取

  2. 创建文件:点击"创建文件"展开面板 → 输入文件名和内容 → 点击"创建"按钮 → 文件出现在列表中 → 面板自动折叠

  3. 查看文件:点击列表中任意文件的"查看"按钮 → 展开内容面板 → 显示文件属性(大小/修改时间/权限八进制值)+ 完整文件内容(等宽字体,最多 20 行)

  4. 管理文件:每个文件提供"复制"(创建 _copy 后缀副本)和"删除"(立即移除)按钮

六、总结

@ohos.file.fs 是 HarmonyOS NEXT 中应用沙箱文件操作的标准模块。通过本文的学习,你应该已经掌握:

  1. 目录浏览listFileSync(path) 列出目录内容(返回名称数组),statSync(path) 获取文件元数据(size/mtime/mode 等 Stat 接口)
  2. 文件读写readTextSync(path) 一次性读取文本文件,openSync(path, mode) + writeSync(fd, data) + closeSync(file) 三步创建和写入文件
  3. 批量操作copyFileSync(src, dest) 复制文件,moveFileSync(src, dest) 移动/重命名,unlinkSync(path) 删除文件
  4. 打开模式OpenMode.CREATE | WRITE_ONLY | TRUNC(创建并覆盖写入)、OpenMode.CREATE | WRITE_ONLY | APPEND(创建并追加写入)
  5. 沙箱限制:所有操作限制在 filesDir/cacheDir/tempDir 内,访问沙箱外路径会抛异常

@ohos.file.fs 的最佳使用模式可以总结为:

listFileSync 发现文件 → statSync 查看属性 → readTextSync 读取小文件内容 → openSync + writeSync + closeSync 三步创建/写入 → copyFileSync/unlinkSync 复制/删除。所有操作都在沙箱内,使用同步版 API 简化代码,异常通过 try/catch 保护。

在 HarmonyOS 的文件管理体系中,@ohos.file.fs 定位于"基础文件 I/O",与 @ohos.file.statvfs(文件系统统计)、@ohos.file.picker(文件选择器)和 @ohos.file.photoPicker(照片选择器)形成完整的文件能力栈。它是应用本地数据持久化最底层的基石——无论是日志写入、JSON 配置存储还是内容缓存,最终都依赖于 @ohos.file.fs 提供的沙箱文件操作。

@ohos.file.fs 属于 @kit.CoreFileKit,所有 API 都提供 Sync/Async 配对版本,操作范围限制在应用沙箱内,无需额外权限。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐