鸿蒙6.1 @ohos.file.fs坑:writeSync/readSync是namespace顶层函数不是File实例方法
鸿蒙 6.1 API 23 开发坑系列篇 8:@ohos.file.fs 文件管理坑——writeSync/readSync 是 namespace 顶层函数不是 File 实例方法 + 第一参传 file.fd 文件描述符根因
本文是「鸿蒙 6.1 API 23 开发坑系列」第 8 篇(非 UI 系第 2 篇)。本篇讲
@ohos.file.fsnamespace(API 6+,鸿蒙 6.1 API 23 基座)——文件读写writeSync/readSync/openSync/closeSync/statSync顶层函数 +File对象 +OpenMode/ReadOptions/WriteOptions类型。鸿蒙坑根因:①writeSync/readSync是 namespace 顶层函数不是File实例方法(file.writeSync()编译错Property does not exist);② 第一参传file.fd文件描述符(number)不是file对象也不是path字符串;③ReadOptions不带encoding(只有offset/length,读出来是ArrayBuffer裸字节自己解码);④WriteOptions带encoding(写字符串时指定编码,写ArrayBuffer不用);⑤fs.closeSync(file)关闭传File对象不是fd(跟writeSync第一参fd不同);⑥OpenModeenum 常量READ_WRITE/CREATE/TRUNC不是flags数字。
一、开篇:鸿蒙 fs 不是 Node fs,是「namespace 顶层函数 + file.fd 文件描述符 + ArrayBuffer 裸字节」
你写 Node 时,文件读写用 fs 模块(fs.writeFileSync/fs.readFileSync 顶层函数,传 path 字符串,读出来是 Buffer/字符串):
// Node fs:fs.writeFileSync 顶层函数传 path,读出来是 Buffer/字符串
import fs from 'fs' // ✅ Node fs 模块
fs.writeFileSync('/tmp/test.txt', 'hello node fs') // ✅ 传 path 字符串,不是 fd
const content: string = fs.readFileSync('/tmp/test.txt', 'utf-8') // ✅ 传 path,第二参 encoding 自动解码
// Node fs.writeFileSync/readFileSync 是顶层函数,传 path 字符串,读出来自动解码到 string
你写鸿蒙 ArkTS 时,文件读写用 fs.writeSync(fd, content) namespace 顶层函数(第一参传 file.fd 文件描述符不是 path,ReadOptions 无 encoding 读出来是 ArrayBuffer 裸字节):
// ArkTS fs.writeSync:namespace 顶层函数第一参传 file.fd,读出来 ArrayBuffer 裸字节自己解码
import fs, { ReadOptions, WriteOptions } from '@ohos.file.fs' // ✅ default import + 类型 named import
import { common } from '@kit.AbilityKit'
import { buffer } from '@kit.ArkTS'
const context = getContext(this) as common.UIAbilityContext
const filePath = context.filesDir + '/test.txt'
// ✅ fs.openSync(path, OpenMode) 造 File 对象(file.fd 是文件描述符 number)
const file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
// ✅ fs.writeSync 是 namespace 顶层函数,第一参传 file.fd 文件描述符(不是 path 字符串)
fs.writeSync(file.fd, 'hello harmony fs') // ✅ 第一参 file.fd 不是 path
// ✅ fs.readSync 读出来是 ArrayBuffer 裸字节(ReadOptions 无 encoding 不自动解码)
const buf = new ArrayBuffer(1024)
const readLen = fs.readSync(file.fd, buf, { offset: 0, length: buf.byteLength } as ReadOptions) // ✅ 无 encoding
const content: string = buffer.from(buf, 0, readLen).toString() // ✅ 自己解码 ArrayBuffer 到 string
// 鸿蒙坑根因:writeSync namespace 顶层函数第一参 file.fd,ReadOptions 无 encoding 读 ArrayBuffer 裸字节
Node fs vs 鸿蒙 fs 的区别:Node 把文件读写当模块顶层函数(fs.writeFileSync(path, content) 传 path 字符串,fs.readFileSync(path, 'utf-8') 传 encoding 自动解码到 string),ArkTS 把文件读写当 namespace 顶层函数(fs.writeSync(file.fd, content) 第一参传 file.fd 文件描述符不是 path,fs.readSync(file.fd, buf, options) 读出来是 ArrayBuffer 裸字节无 encoding 不自动解码)。根因不是模块函数是 namespace 顶层函数——鸿蒙 writeSync/readSync 第一参传 file.fd 文件描述符(先 openSync 造 File 对象拿 fd),ReadOptions 无 encoding 读出来是 ArrayBuffer 裸字节自己用 buffer.from().toString() 解码。
二、根因:鸿蒙 @ohos.file.fs 的六个绑定机制
鸿蒙 @ohos.file.fs namespace(API 6+)核心导出 fs.openSync/fs.writeSync/fs.readSync/fs.closeSync/fs.statSync 顶层函数 + File interface + OpenMode/ReadOptions/WriteOptions/Stat 类型。绑定机制来自六重根因。
机制 1:writeSync/readSync 是 namespace 顶层函数不是 File 实例方法
鸿蒙坑根因:writeSync/readSync 是 fs namespace 顶层函数,不是 File 实例方法:
// ❌ 鸿蒙坑:writeSync/readSync 是 namespace 顶层函数不是 File 实例方法
import fs from '@ohos.file.fs'
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
// ❌ File 实例方法不存在(编译错 Property does not exist)
file.writeSync('content') // ❌ File interface 没有 writeSync 实例方法
file.readSync(buffer) // ❌ File interface 没有 readSync 实例方法
// ✅ 正确用法:fs.writeSync/fs.readSync namespace 顶层函数,第一参传 file.fd
fs.writeSync(file.fd, 'content') // ✅ namespace 顶层函数 + file.fd
fs.readSync(file.fd, buffer, options) // ✅ namespace 顶层函数 + file.fd
// 鸿蒙坑根因:writeSync/readSync 是 namespace 顶层函数不是 File 实例方法,第一参传 file.fd
namespace 顶层函数坑根因:鸿蒙 @ohos.file.fs.d.ts 的 writeSync/readSync 声明是 export function writeSync(fd: number, ...) 和 export function readSync(fd: number, ...)(namespace 顶层函数,不是 File interface 的方法)。File interface 只有 fd/name/path 属性没有读写方法。鸿蒙坑:file.writeSync() 触发 Property 'writeSync' does not exist on type 'File' 编译错——File 是数据对象(持 fd/name/path)不是读写对象,读写必须走 fs.writeSync(file.fd, ...) namespace 顶层函数。Node fs.writeFileSync 也是模块顶层函数但传 path 字符串,鸿蒙 fs.writeSync 传 file.fd 文件描述符(先 openSync 拿 fd)。
机制 2:第一参传 file.fd 文件描述符不是 file 对象也不是 path 字符串
鸿蒙坑根因:writeSync/readSync 第一参传 file.fd 文件描述符(number),不是 file 对象也不是 path 字符串:
// ❌ 鸿蒙坑:第一参传 file.fd 文件描述符不是 file 对象也不是 path 字符串
import fs from '@ohos.file.fs'
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
// ❌ 传 file 对象编译错(writeSync 第一参类型是 number 不是 File)
fs.writeSync(file, 'content') // ❌ 第一参类型 number 不是 File 对象
// ❌ 传 path 字符串编译错(writeSync 第一参不是 path)
fs.writeSync('/tmp/test.txt', 'content') // ❌ 第一参不是 path 字符串是 fd
// ✅ 正确用法:第一参传 file.fd 文件描述符(number 类型)
fs.writeSync(file.fd, 'content') // ✅ file.fd 是 number 文件描述符
// 鸿蒙坑根因:第一参传 file.fd 文件描述符(number),不是 file 对象也不是 path 字符串
file.fd 文件描述符坑根因:鸿蒙 fs.writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions) 的第一参类型是 number(文件描述符 fd),不是 File 对象也不是 path 字符串。fs.openSync(path, OpenMode) 返回 File 对象,file.fd 是 number 类型的文件描述符。鸿蒙坑:传 file 对象触发 Type 'File' is not assignable to type 'number' 编译错,传 path 字符串触发 Type 'string' is not assignable to type 'number' 编译错——必须传 file.fd(先 openSync 拿 fd 再传给 writeSync/readSync)。Node fs.writeFileSync(path, content) 传 path 字符串不需要先 open,鸿蒙 fs.writeSync(file.fd, content) 必须先 openSync 拿 fd。
机制 3:ReadOptions 不带 encoding——读出来是 ArrayBuffer 裸字节自己解码
鸿蒙坑根因:ReadOptions 不带 encoding(只有 offset/length),读出来是 ArrayBuffer �裸字节自己解码:
// ❌ 鸿蒙坑:ReadOptions 不带 encoding(读出来是 ArrayBuffer 裸字节)
import fs, { ReadOptions } from '@ohos.file.fs'
import { buffer } from '@kit.ArkTS'
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
fs.writeSync(file.fd, 'hello h8 fs')
// ❌ ReadOptions 带 encoding 编译错(encoding 不在 ReadOptions 类型里)
const badReadOptions: ReadOptions = { offset: 0, length: 20, encoding: 'utf-8' } // ❌ encoding 不存在
// ✅ 正确用法:ReadOptions 只有 offset/length,读出来是 ArrayBuffer 裸字节
const arrayBuffer = new ArrayBuffer(1024)
const readOptions: ReadOptions = { offset: 0, length: arrayBuffer.byteLength } // ✅ 无 encoding
const readLen = fs.readSync(file.fd, arrayBuffer, readOptions) // ✅ 读出来是 ArrayBuffer 裸字节
// ✅ 用 @kit.ArkTS buffer 自己解码 ArrayBuffer 到 string(鸿蒙不自动解码)
const content: string = buffer.from(arrayBuffer, 0, readLen).toString() // ✅ buffer.toString() 解码
// 鸿蒙坑根因:ReadOptions 无 encoding 读出来 ArrayBuffer 裸字节,用 buffer.from().toString() 自己解码
ReadOptions 无 encoding 坑根因:鸿蒙 ReadOptions 的属性只有 offset?: number(读取偏移)和 length?: number(读取长度),没有 encoding 字段。fs.readSync 读出来是 ArrayBuffer 裸字节(二进制),不自动解码到 string。鸿蒙坑:ReadOptions 带 encoding 触发 Object literal may only specify known properties, and 'encoding' does not exist in type 'ReadOptions' 编译错——读出来的 ArrayBuffer 必须用 @kit.ArkTS 的 buffer.from(arrayBuffer, 0, readLen).toString() 自己解码到 string。Node fs.readFileSync(path, 'utf-8') 第二参传 encoding 自动解码到 string,鸿蒙 fs.readSync(fd, buf, options) 的 ReadOptions 无 encoding 不自动解码——读 ArrayBuffer �裸字节自己解码。
机制 4:WriteOptions 带 encoding——写字符串时指定编码
鸿蒙坑根因:WriteOptions 带 encoding(写字符串时指定编码,写 ArrayBuffer 不用):
// ✅ WriteOptions 带 encoding(写字符串时指定编码,写 ArrayBuffer 不用)
import fs, { WriteOptions } from '@ohos.file.fs'
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
// ✅ WriteOptions 带 encoding(写字符串时指定 utf-8 编码)
const writeOptions: WriteOptions = { offset: 0, length: 11, encoding: 'utf-8' } // ✅ 带 encoding
fs.writeSync(file.fd, 'hello h8 enc', writeOptions) // ✅ 写字符串带 encoding
// ✅ 写 ArrayBuffer 不用 encoding(二进制直接写)
const buf = new ArrayBuffer(10)
const writeOptions2: WriteOptions = { offset: 0, length: 10 } // ✅ 写 ArrayBuffer 不用 encoding
fs.writeSync(file.fd, buf, writeOptions2)
// 鸿蒙坑根因:WriteOptions 带 encoding(写字符串时指定编码),ReadOptions 不带 encoding
WriteOptions 带 encoding 坑根因:鸿蒙 WriteOptions 的属性是 offset?: number/length?: number/encoding?: string(带 encoding),跟 ReadOptions(无 encoding)不同。鸿蒙坑:WriteOptions 带 encoding 指定写字符串时的编码('utf-8'/'utf-16' 等),写 ArrayBuffer 二进制不用 encoding(直接写裸字节);ReadOptions 无 encoding 读出来是 ArrayBuffer 裸字节。Node fs.writeFileSync(path, content, { encoding: 'utf-8' }) 的 encoding 是可选的(写字符串默认 utf-8),鸿蒙 WriteOptions.encoding 也是可选的但写字符串时显式指定更安全。鸿蒙坑核心:ReadOptions 无 encoding 读 ArrayBuffer 裸字节自己解码,WriteOptions 带 encoding 写字符串时指定编码——读写 encoding 不对称。
机制 5:closeSync(file) 关闭传 File 对象不是 fd——跟 writeSync 第一参 fd 不同
鸿蒙坑根因:fs.closeSync(file) 关闭传 File 对象不是 fd(跟 writeSync 第一参 fd 不同):
// ❌ 鸿蒙坑:closeSync(file) 关闭传 File 对象不是 fd(跟 writeSync 第一参 fd 不同)
import fs from '@ohos.file.fs'
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
fs.writeSync(file.fd, 'content')
// ❌ closeSync 传 fd 编译错(closeSync 第一参类型是 File 不是 number)
fs.closeSync(file.fd) // ❌ 第一参类型 File 不是 number(file.fd 是 number)
// ✅ 正确用法:closeSync(file) 传 File 对象(不是 file.fd 文件描述符)
fs.closeSync(file) // ✅ 传 File 对象不是 fd
// 鸿蒙坑根因:closeSync(file) 传 File 对象,writeSync(file.fd, ...) 传 fd——两个第一参类型不同
closeSync vs writeSync 第一参坑根因:鸿蒙 fs.closeSync(file: File): void 的第一参类型是 File 对象,跟 fs.writeSync(fd: number, ...) 的第一参类型 number(fd)不同。鸿蒙坑:fs.closeSync(file.fd) 触发 Type 'number' is not assignable to type 'File' 编译错——closeSync 传 File 对象(file),writeSync/readSync 传 fd(file.fd),两个第一参类型不同。Node fs.closeSync(fd) 传 fd 数字(跟 fs.openSync 返回的 fd 一致),鸿蒙 fs.closeSync(file) 传 File 对象——鸿蒙的 closeSync 和 writeSync/readSync 第一参类型不一致是坑。
机制 6:OpenMode enum 常量 READ_WRITE/CREATE/TRUNC 不是 flags 数字
鸿蒙坑根因:OpenMode enum 常量 READ_ONLY/WRITE_ONLY/READ_WRITE/CREATE/TRUNC/APPEND,不是 flags 数字:
// ❌ 鸿蒙坑:OpenMode enum 常量不是 flags 数字(fs.openSync 第二参用 OpenMode 不用数字)
import fs from '@ohos.file.fs'
// ❌ 传 flags 数字编译错(openSync 第二参类型是 OpenMode enum 不是 number)
const badFile = fs.openSync('/tmp/test.txt', 0o666) // ❌ 第二参类型 OpenMode 不是 number
// ❌ 传字符串 flags 编译错(不是 'r'/'w'/'r+' 字符串)
const badFile2 = fs.openSync('/tmp/test.txt', 'r+') // ❌ 不是字符串 flags 是 OpenMode enum
// ✅ 正确用法:OpenMode enum 常量 | 位运算组合(READ_WRITE | CREATE | TRUNC)
const file = fs.openSync('/tmp/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC) // ✅ OpenMode enum
// ✅ OpenMode enum 常量:READ_ONLY=0o0 / WRITE_ONLY=0o1 / READ_WRITE=0o2 / CREATE=0o100 / TRUNC=0o1000 / APPEND=0o2000
// 鸿蒙坑根因:OpenMode enum 常量 | 位运算组合,不是 flags 数字也不是 'r'/'w' 字符串
OpenMode enum 坑根因:鸿蒙 fs.openSync(path: string, mode: OpenMode): File 的第二参类型是 OpenMode enum(位标志 enum),常量 READ_ONLY=0o0/WRITE_ONLY=0o1/READ_WRITE=0o2/CREATE=0o100/TRUNC=0o1000/APPEND=0o2000,用 | 位运算组合。鸿蒙坑:传 flags 数字触发 Type 'number' is not assignable to type 'OpenMode' 编译错,传字符串 'r+'/'w' 触发 Type 'string' is not assignable to type 'OpenMode' 编译错——必须用 fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE enum 常量位运算。Node fs.openSync(path, 'r+') 传字符串 flags,鸿蒙 fs.openSync(path, OpenMode.READ_WRITE) 传 enum 常量;Node fs.openSync(path, 0o666) 传数字 mode,鸿蒙传 OpenMode enum 不是数字。
三、真机配图:鸿蒙 @ohos.file.fs 文件管理坑——namespace 顶层函数 + file.fd + ReadOptions 无 encoding


真机配图展示鸿蒙 @ohos.file.fs 文件管理坑:
- 初始态:鸿蒙 6.1 @ohos.file.fs 文件管理坑标题,4 个验证按钮(① writeSync namespace 顶层函数 / ② ReadOptions 无 encoding / ③ WriteOptions 带 encoding / ④ openSync+closeSync+statSync 生命周期),文件状态(writeStatus 未写 + readStatus 未读 + fdValue 未开 + writeLen/readLen/readContent),要点说明 7 条
- writeSync namespace 顶层函数态:点击「① 验证 writeSync namespace 顶层函数」按钮,显示「✅ fs.writeSync namespace 顶层函数验证:不是 File 实例方法,第一参传 file.fd」+ file.fd 值 + writeLen——writeSync namespace 顶层函数 + file.fd 验证
- ReadOptions 无 encoding 态:点击「② 验证 ReadOptions 无 encoding」按钮,显示「✅ ReadOptions 无 encoding 验证:读出来是 ArrayBuffer,用 buffer.toString() 自己解码」+ readLen + readContent——ReadOptions 无 encoding 读 ArrayBuffer 裸字节验证
- WriteOptions 带 encoding 态:点击「③ 验证 WriteOptions 带 encoding」按钮,显示「✅ WriteOptions 带 encoding 验证:写字符串时指定 utf-8 编码」+ writeLen——WriteOptions 带 encoding 写字符串指定编码验证
- openSync+closeSync+statSync 生命周期态:点击「④ 验证 openSync+closeSync+statSync 生命周期」按钮,显示「✅ 文件生命周期验证:openSync + writeSync + statSync + closeSync」+ file.fd + stat.size 值——完整文件生命周期验证
四、真解法:鸿蒙 @ohos.file.fs 的四个场景
场景 1:openSync 造 File + writeSync(file.fd) 写文件 + closeSync(file) 关闭——90% 场景首选
基础文件写入用 fs.openSync 造 File + fs.writeSync(file.fd, content) 写 + fs.closeSync(file) 关闭:
// ✅ 场景 1:openSync 造 File + writeSync(file.fd) 写文件 + closeSync(file) 关闭(API 6,90% 场景首选)
import fs, { WriteOptions } from '@ohos.file.fs' // ✅ default import + 类型 named import
import { common } from '@kit.AbilityKit'
@Entry
@Component
struct Index {
@State writeStatus: string = '(未写)'
private file: fs.File | null = null // ✅ 持引用避免析构
writeToFile() {
// ✅ 获取应用沙箱目录路径(getContext(this) deprecated 但能跑,新版用 this.getUIContext.getHostContext)
const context = getContext(this) as common.UIAbilityContext
const filePath = context.filesDir + '/h8_demo.txt'
// ✅ fs.openSync(path, OpenMode) 造 File 对象(OpenMode enum 常量 | 位运算组合)
this.file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC)
// ✅ fs.writeSync(file.fd, content) namespace 顶层函数——第一参 file.fd 不是 path
const writeOptions: WriteOptions = { encoding: 'utf-8' } // ✅ WriteOptions 带 encoding
const writeLen = fs.writeSync(this.file.fd, 'hello h8 fs writeSync', writeOptions)
this.writeStatus = `✅ writeSync 写入 ${writeLen} 字节到 file.fd=${this.file.fd}`
// ✅ fs.closeSync(file) 关闭传 File 对象不是 fd(跟 writeSync 第一参 fd 不同)
fs.closeSync(this.file) // ✅ 传 File 对象不是 file.fd
this.file = null
}
build() { Column({ space: 8 }) { Text(this.writeStatus).fontSize(12) } }
}
// openSync + writeSync(file.fd) + closeSync(file):90% 场景首选,namespace 顶层函数 + file.fd
鸿蒙 @ohos.file.fs API 真名坑:import fs, { ReadOptions, WriteOptions } from '@ohos.file.fs'(default import + 类型 named import,ReadOptions/WriteOptions 是 named export 不是嵌套在 namespace 里);fs.openSync(path: string, mode: OpenMode): File(造 File 对象,OpenMode enum 常量不是 flags 数字);fs.writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): number(namespace 顶层函数,第一参 fd 文件描述符不是 path);fs.readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number(读出来是 ArrayBuffer 裸字节);fs.closeSync(file: File): void(关闭传 File 对象不是 fd);fs.statSync(file: string | number | File): Stat(获取文件信息,Stat.size 是文件大小);SysCap SystemCapability.FileManagement.File.FileIO;权限 无需特殊权限(应用沙箱目录内读写)。
场景 2:readSync 读 ArrayBuffer 裸字节 + buffer.from().toString() 自己解码
读文件用 fs.readSync(file.fd, buf, ReadOptions) 读 ArrayBuffer 裸字节 + buffer.from().toString() 解码:
// ✅ 场景 2:readSync 读 ArrayBuffer 裸字节 + buffer.from().toString() 自己解码(API 6)
import fs, { ReadOptions } from '@ohos.file.fs'
import { common } from '@kit.AbilityKit'
import { buffer } from '@kit.ArkTS' // ✅ @kit.ArkTS buffer 解码 ArrayBuffer
const context = getContext(this) as common.UIAbilityContext
const filePath = context.filesDir + '/h8_demo.txt'
const file = fs.openSync(filePath, fs.OpenMode.READ_ONLY) // ✅ 只读模式打开
// ✅ ReadOptions 无 encoding(只有 offset/length),读出来是 ArrayBuffer 裸字节
const arrayBuffer = new ArrayBuffer(1024)
const readOptions: ReadOptions = { offset: 0, length: arrayBuffer.byteLength } // ✅ 无 encoding
const readLen = fs.readSync(file.fd, arrayBuffer, readOptions) // ✅ 读 ArrayBuffer 裸字节
// ✅ buffer.from(arrayBuffer, 0, readLen).toString() 解码 ArrayBuffer 到 string
const content: string = buffer.from(arrayBuffer, 0, readLen).toString() // ✅ 自己解码
console.info('文件内容: ' + content) // ✅ content 是解码后的 string
fs.closeSync(file)
// readSync ArrayBuffer 裸字节 + buffer.toString() 解码:ReadOptions 无 encoding 自己解码
鸿蒙 readSync + buffer 解码 API 真名坑:fs.readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number(返回读取字节数,读出来是 ArrayBuffer 裸字节不是 string);ReadOptions 只有 offset?: number/length?: number 无 encoding;@kit.ArkTS 的 buffer.from(arrayBuffer, byteOffset, length).toString() 解码 ArrayBuffer 到 string;鸿蒙坑:Node fs.readFileSync(path, 'utf-8') 第二参传 encoding 自动解码到 string,鸿蒙 fs.readSync(fd, buf, options) 的 ReadOptions 无 encoding 读出来 ArrayBuffer 裸字节——必须用 buffer.from().toString() 自己解码(@kit.ArkTS 的 buffer 不是 Node 的 Buffer)。
场景 3:WriteOptions 带 encoding 写字符串 + 不带 encoding 写 ArrayBuffer
写字符串用 WriteOptions.encoding 指定编码,写 ArrayBuffer 不用 encoding:
// ✅ 场景 3:WriteOptions 带 encoding 写字符串 + 不带 encoding 写 ArrayBuffer(API 6)
import fs, { WriteOptions } from '@ohos.file.fs'
const file = fs.openSync('/tmp/h8_enc.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC)
// ✅ 写字符串带 encoding(指定 utf-8 编码)
const strOptions: WriteOptions = { offset: 0, length: 11, encoding: 'utf-8' } // ✅ 带 encoding
fs.writeSync(file.fd, 'hello h8 enc', strOptions) // ✅ 写字符串带 encoding
// ✅ 写 ArrayBuffer 不用 encoding(二进制直接写裸字节)
const buf = new ArrayBuffer(10)
const binOptions: WriteOptions = { offset: 0, length: 10 } // ✅ 写 ArrayBuffer 不用 encoding
fs.writeSync(file.fd, buf, binOptions) // ✅ 写 ArrayBuffer 不用 encoding
fs.closeSync(file)
// WriteOptions 带 encoding 写字符串 + 不带 encoding 写 ArrayBuffer:读写 encoding 不对称
鸿蒙 WriteOptions encoding API 真名坑:WriteOptions 属性 offset?: number/length?: number/encoding?: string(带 encoding);写字符串时 encoding 指定编码('utf-8'/'utf-16'),写 ArrayBuffer 二进制不用 encoding;鸿蒙坑:ReadOptions 无 encoding 读 ArrayBuffer 裸字节自己解码,WriteOptions 带 encoding 写字符串时指定编码——读写 encoding 不对称是鸿蒙坑核心。Node fs.writeFileSync(path, string, { encoding: 'utf-8' }) 和 fs.readFileSync(path, 'utf-8') 读写都带 encoding,鸿蒙只有 WriteOptions 带 encoding,ReadOptions 无 encoding。
场景 4:statSync 获取文件信息 + listFileSync 列目录 + unlinkSync 删除
文件信息用 fs.statSync,列目录用 fs.listFileSync,删除用 fs.unlinkSync:
// ✅ 场景 4:statSync 获取文件信息 + listFileSync 列目录 + unlinkSync 删除(API 6)
import fs from '@ohos.file.fs'
const file = fs.openSync('/tmp/h8_stat.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
fs.writeSync(file.fd, 'stat demo')
// ✅ fs.statSync(file) 获取文件信息(file 可以是 path 或 fd 或 File)
const stat = fs.statSync(file.fd) // ✅ 传 fd(也可以传 path 或 File 对象)
console.info('文件大小: ' + stat.size) // ✅ Stat.size 是文件字节数
console.info('修改时间: ' + stat.modifiedTime) // ✅ Stat.modifiedTime 是修改时间
fs.closeSync(file)
// ✅ fs.listFileSync(path) 列目录文件(返回 string[] 文件名数组)
const files: string[] = fs.listFileSync('/tmp') // ✅ 返回目录下文件名数组
console.info('目录文件数: ' + files.length)
// ✅ fs.unlinkSync(path) 删除文件(传 path 字符串不是 fd)
fs.unlinkSync('/tmp/h8_stat.txt') // ✅ 传 path 字符串删除文件
// statSync + listFileSync + unlinkSync:statSync 传 fd/path/File,unlinkSync 传 path
鸿蒙 statSync + listFileSync + unlinkSync API 真名坑:fs.statSync(file: string | number | File): Stat(获取文件信息,第一参可以是 path 字符串/fd 数字/File 对象三选一,跟 writeSync 只传 fd 不同);fs.listFileSync(path: string): string[](列目录文件名数组);fs.unlinkSync(path: string): void(删除文件,传 path 字符串不是 fd);Stat 属性 size: number/modifiedTime: number/hasNoAccess: boolean;鸿蒙坑:statSync 第一参可以是 path/fd/File 三种类型(比 writeSync 只传 fd 姬活),unlinkSync 传 path 字符串不是 fd(跟 closeSync 传 File 又不同)——鸿蒙 fs 各函数第一参类型不统一是坑(writeSync/readSync 传 fd,closeSync 传 File,unlinkSync 传 path,statSync 传 path/fd/File)。
五、一句话哲学
写鸿蒙 ArkTS 记住:fs 不是 Node fs 是「namespace 顶层函数 + file.fd 文件描述符 + ArrayBuffer 裸字节」——鸿蒙 6.1 API 23
@ohos.file.fsnamespace(API 6+,鸿蒙 6.1 API 23 基座,fs.openSync/writeSync/readSync/closeSync/statSync/listFileSync/unlinkSync顶层函数 +Fileinterface +OpenMode/ReadOptions/WriteOptions/Stat类型,SysCap SystemCapability.FileManagement.File.FileIO,无需特殊权限应用沙箱内读写)。根因不是模块函数是 namespace 顶层函数——writeSync/readSync是 namespace 顶层函数不是File实例方法(✅fs.writeSync(file.fd, content)namespace 顶层函数,❌file.writeSync()编译错Property 'writeSync' does not exist on type 'File',Fileinterface 只有fd/name/path属性无读写方法),第一参传file.fd文件描述符(number)不是file对象也不是path字符串(✅fs.writeSync(file.fd, ...)第一参number,❌fs.writeSync(file, ...)触发Type 'File' is not assignable to type 'number',❌fs.writeSync('/path', ...)触发Type 'string' is not assignable to type 'number',先openSync拿 fd 再传给writeSync/readSync),ReadOptions不带encoding(只有offset/length,读出来是ArrayBuffer裸字节,用@kit.ArkTS buffer.from(buf, 0, readLen).toString()自己解码,❌ReadOptions带encoding触发Object literal may only specify known properties, and 'encoding' does not exist编译错),WriteOptions带encoding(写字符串时指定'utf-8'编码,写 ArrayBuffer 不用),读写 encoding 不对称是鸿蒙坑核心(WriteOptions带 encoding,ReadOptions无 encoding),fs.closeSync(file)关闭传File对象不是fd(跟writeSync第一参fd类型不同,❌closeSync(file.fd)触发Type 'number' is not assignable to type 'File'),OpenModeenum 常量READ_ONLY/WRITE_ONLY/READ_WRITE/CREATE/TRUNC/APPEND位运算组合不是 flags 数字也不是'r'/'w'字符串,各函数第一参类型不统一(writeSync/readSync传 fd,closeSync传 File,unlinkSync传 path,statSync传 path/fd/File 三选一)。namespace 顶层函数 + file.fd + ReadOptions 无 encoding + WriteOptions 带 encoding + closeSync File + OpenMode enum 是鸿蒙 6.1 @ohos.file.fs 文件管理坑核心!
能力系列回链
- 鸿蒙 7.0 新特性篇 1~17(沉浸式毛玻璃/Component3D/智能体框架/方舟引擎/星盾安全/星河互联/空间音频/可变字体/游戏快启/分布式数据盾/LTPO 可变帧率/AI 文档识别/多形态服务窗口/AI 反诈/机密计算/空间计算/小艺全面进化)
- 鸿蒙 6.1 API 23 开发坑系列篇 1「ArkUI.modifier 装饰器坑」——attributeModifier + AttributeModifier 状态化节点修改器
- 鸿蒙 6.1 API 23 开发坑系列篇 2「arkui.componentSnapshot 组件截图坑」——get/getSync/createFromBuilder 返回 image.PixelMap 像素图
- 鸿蒙 6.1 API 23 开发坑系列篇 3「arkui.node 节点坑」——NodeController abstract class makeNode override + BuilderNode WrappedBuilder
- 鸿蒙 6.1 API 23 开发坑系列篇 4「arkui.UIContext UI 上下文坑」——runScopedTask 不是 runScopedOnUiThread + 11 个子管理器
- 鸿蒙 6.1 API 23 开发坑系列篇 5「arkui.observer UI 观察器坑」——uiObserver namespace 真名不是 observer + on type string literal
- 鸿蒙 6.1 API 23 开发坑系列篇 6「@ohos.animator 动画器坑」——import @kit.ArkUI 不是 @ohos.animator + onFrame 驼峰不是废弃 onframe + getUIContext().createAnimator 不是废弃 animator.create + 持引用 + aboutToDisappear cancel
- 鸿蒙 6.1 API 23 开发坑系列篇 7「@ohos.net.http HTTP 请求坑」——HttpDataType 常量是 STRING 不是 STRING_TYPE + HttpRequest 是 interface 不能 new + http.createHttp() 工厂造实例 + on/off 监听不是 addEventListener + header Record 不是 Headers + RequestMethod enum 不是字符串
- 鸿蒙 6.1 API 23 开发坑系列篇 8「@ohos.file.fs 文件管理坑」——writeSync/readSync 是 namespace 顶层函数不是 File 实例方法 + 第一参传 file.fd 文件描述符 + ReadOptions 无 encoding 读 ArrayBuffer 裸字节 + WriteOptions 带 encoding 写字符串指定编码 + closeSync(file) 传 File 不是 fd + OpenMode enum 不是 flags 数字(本文)
更多推荐


所有评论(0)