import fileUri from '@ohos.file.fileuri';
import fs, { ListFileOptions, ReadOptions, ReadTextOptions, WriteOptions } from '@ohos.file.fs';
import { StrUtil } from './StrUtil';
import { fileShare } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';/*** 文件操作相关工具类** @author 鸿蒙布道师* @since 2025/04/07*/
export class FileUtil {static readonly separator: string = '/'; // 文件路径分隔符/*** 获取文件目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getFilesDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().filesDir : getContext().getApplicationContext().filesDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 获取缓存目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getCacheDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().cacheDir : getContext().getApplicationContext().cacheDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 获取临时目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getTempDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().tempDir : getContext().getApplicationContext().tempDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 构建文件路径的通用逻辑。** @param rootPath 根目录路径。* @param dirPath 子目录路径。* @param fileName 文件名。* @returns 返回完整的文件路径。*/private static buildFilePath(rootPath: string, dirPath: string, fileName: string): string {let filePath = rootPath;if (StrUtil.isNotEmpty(dirPath)) {if (FileUtil.hasDirPath(dirPath)) { // 路径中包含根目录,是完整路径。filePath = dirPath;} else { // 路径中不包含根目录,拼接成完整路径。filePath = `${filePath}${FileUtil.separator}${dirPath}`;}if (!FileUtil.accessSync(filePath)) {FileUtil.mkdirSync(filePath); // 如果文件夹不存在就创建。}}if (StrUtil.isNotEmpty(fileName)) {filePath = `${filePath}${FileUtil.separator}${fileName}`;}return filePath;}/*** 判断是否是完整路径。** @param path 文件路径。* @returns 返回布尔值,表示是否是完整路径。*/static hasDirPath(path: string): boolean {return StrUtil.startsWith(path, "/data/storage/") || StrUtil.startsWith(path, "/storage/");}/*** 通过 URI 或路径,获取 FileUri 对象。** @param uriOrPath URI 或路径。* @returns 返回 FileUri 对象。*/static getFileUri(uriOrPath: string): fileUri.FileUri {return new fileUri.FileUri(uriOrPath);}/*** 通过 URI 或路径,获取文件名。** @param uriOrPath URI 或路径。* @returns 返回文件名。*/static getFileName(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).name;}/*** 通过 URI 或路径,获取文件路径。** @param uriOrPath URI 或路径。* @returns 返回文件路径。*/static getFilePath(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).path;}/*** 通过 URI 或路径,获取对应文件父目录的 URI。** @param uriOrPath URI 或路径。* @returns 返回父目录的 URI。*/static getParentUri(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).getFullDirectoryUri();}/*** 通过 URI 或路径,获取对应文件父目录的路径名。** @param uriOrPath URI 或路径。* @returns 返回父目录的路径名。*/static getParentPath(uriOrPath: string): string {const parentUri = FileUtil.getParentUri(uriOrPath);return FileUtil.getFilePath(parentUri);}/*** 以同步方法获取文件 URI。** @param path 应用沙箱路径。* @returns 返回文件 URI。*/static getUriFromPath(path: string): string {return fileUri.getUriFromPath(path);}/*** 根据文件名获取文件后缀。** @param fileName 文件名(如 `test.txt` 或 `test.doc`)。* @returns 返回文件后缀(如 `txt` 或 `doc`)。*/static getFileExtension(fileName: string): string {if (StrUtil.isNotEmpty(fileName) && fileName.includes(".")) {return fileName.substring(fileName.lastIndexOf(".") + 1);}return '';}/*** 获取指定文件夹下所有文件的大小或指定文件的大小。** @param path 文件夹路径或文件路径。* @returns 返回文件或文件夹的总大小(单位:字节)。*/static getFileDirSize(path: string): number {if (!FileUtil.accessSync(path)) {return 0; // 路径不存在时返回 0。}if (FileUtil.isDirectory(path)) { // 文件夹let totalSize = 0;FileUtil.listFileSync(path, { recursion: true }).forEach((filePath) => {try {totalSize += FileUtil.statSync(filePath).size;} catch (error) {console.warn(`Failed to get size for file ${filePath}. Error: ${error.message}`);}});return totalSize;} else { // 文件return FileUtil.statSync(path).size;}}/*** 判断文件是否是普通文件。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @returns 返回布尔值,表示是否是普通文件。*/static isFile(file: string | number): boolean {try {return fs.statSync(file).isFile();} catch (error) {throw new Error(`Failed to check if file is a regular file. Path/FD: ${file}. Error: ${error.message}`);}}/*** 判断文件是否是目录。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @returns 返回布尔值,表示是否是目录。*/static isDirectory(file: string | number): boolean {try {return fs.statSync(file).isDirectory();} catch (error) {throw new Error(`Failed to check if file is a directory. Path/FD: ${file}. Error: ${error.message}`);}}/*** 重命名文件或文件夹,使用 Promise 异步回调。** @param oldPath 文件的应用沙箱原路径。* @param newPath 文件的应用沙箱新路径。* @returns 返回一个无返回值的 Promise。*/static rename(oldPath: string, newPath: string): Promise<void> {return fs.rename(oldPath, newPath).catch((error:BusinessError) => {throw new Error(`Failed to rename file/directory from ${oldPath} to ${newPath}. Error: ${error.message}`);});}/*** 重命名文件或文件夹,以同步方法。** @param oldPath 文件的应用沙箱原路径。* @param newPath 文件的应用沙箱新路径。*/static renameSync(oldPath: string, newPath: string): void {try {fs.renameSync(oldPath, newPath);} catch (error) {throw new Error(`Failed to rename file/directory from ${oldPath} to ${newPath}. Error: ${error.message}`);}}/*** 创建目录,支持多层级创建。** @param path 目录的应用沙箱路径。* @param recursion 是否多层级创建目录:* - `true`:递归创建多级目录。* - `false`:仅创建单层目录。* @returns 返回一个无返回值的 Promise。*/static mkdir(path: string, recursion: boolean = true): Promise<void> {return fs.mkdir(path, recursion).catch((error:BusinessError) => {throw new Error(`Failed to create directory at ${path}. Recursion: ${recursion}. Error: ${error.message}`);});}/*** 创建目录,以同步方法,支持多层级创建。** @param path 目录的应用沙箱路径。* @param recursion 是否多层级创建目录:* - `true`:递归创建多级目录。* - `false`:仅创建单层目录。*/static mkdirSync(path: string, recursion: boolean = true): void {try {fs.mkdirSync(path, recursion);} catch (error) {throw new Error(`Failed to create directory at ${path}. Recursion: ${recursion}. Error: ${error.message}`);}}/*** 删除整个目录。** @param path 目录的应用沙箱路径。* @returns 返回一个无返回值的 Promise。*/static rmdir(path: string): Promise<void> {return fs.rmdir(path).catch((error:BusinessError) => {throw new Error(`Failed to remove directory at ${path}. Error: ${error.message}`);});}/*** 删除整个目录,以同步方法。** @param path 目录的应用沙箱路径。*/static rmdirSync(path: string): void {try {fs.rmdirSync(path);} catch (error) {throw new Error(`Failed to remove directory at ${path}. Error: ${error.message}`);}}/*** 删除单个文件。** @param path 文件的应用沙箱路径。* @returns 返回一个无返回值的 Promise。*/static unlink(path: string): Promise<void> {return fs.unlink(path).catch((error:BusinessError) => {throw new Error(`Failed to delete file at ${path}. Error: ${error.message}`);});}/*** 删除单个文件,以同步方法。** @param path 文件的应用沙箱路径。*/static unlinkSync(path: string): void {try {fs.unlinkSync(path);} catch (error) {throw new Error(`Failed to delete file at ${path}. Error: ${error.message}`);}}/*** 检查文件是否存在。** @param path 文件应用沙箱路径。* @returns 返回一个布尔值的 Promise。*/static access(path: string): Promise<boolean> {return fs.access(path).catch((error:BusinessError) => {throw new Error(`Failed to check file existence at ${path}. Error: ${error.message}`);});}/*** 检查文件是否存在,以同步方法。** @param path 文件应用沙箱路径。* @returns 返回布尔值,表示文件是否存在。*/static accessSync(path: string): boolean {try {return fs.accessSync(path);} catch (error) {throw new Error(`Failed to check file existence at ${path}. Error: ${error.message}`);}}/*** 打开文件,支持使用 URI 打开。** @param path 文件的应用沙箱路径或 URI。* @param mode 打开文件的选项,默认为只读方式打开。* @returns 返回文件对象的 Promise。*/static open(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): Promise<fs.File> {return fs.open(path, mode).catch((error:BusinessError) => {throw new Error(`Failed to open file at ${path}. Mode: ${mode}. Error: ${error.message}`);});}/*** 打开文件,支持使用 URI 打开,以同步方法。** @param path 文件的应用沙箱路径或 URI。* @param mode 打开文件的选项,默认为只读方式打开。* @returns 返回文件对象。*/static openSync(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): fs.File {try {return fs.openSync(path, mode);} catch (error) {throw new Error(`Failed to open file at ${path}. Mode: ${mode}. Error: ${error.message}`);}}/*** 从文件读取数据。** @param fd 已打开的文件描述符。* @param buffer 用于保存读取到的文件数据的缓冲区。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* @returns 返回实际读取的数据长度的 Promise。*/static read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise<number> {return fs.read(fd, buffer, options).catch((error:BusinessError) => {throw new Error(`Failed to read file data. FD: ${fd}. Error: ${error.message}`);});}/*** 从文件读取数据,以同步方法。** @param fd 已打开的文件描述符。* @param buffer 用于保存读取到的文件数据的缓冲区。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* @returns 返回实际读取的数据长度。*/static readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number {try {return fs.readSync(fd, buffer, options);} catch (error) {throw new Error(`Failed to read file data. FD: ${fd}. Error: ${error.message}`);}}/*** 基于文本方式读取文件内容。** @param filePath 文件的应用沙箱路径。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回文件内容的 Promise。*/static readText(filePath: string, options?: ReadTextOptions): Promise<string> {return fs.readText(filePath, options).catch((error:BusinessError) => {throw new Error(`Failed to read text file at ${filePath}. Error: ${error.message}`);});}/*** 基于文本方式读取文件内容,以同步方法。** @param filePath 文件的应用沙箱路径。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回文件内容。*/static readTextSync(filePath: string, options?: ReadTextOptions): string {try {return fs.readTextSync(filePath, options);} catch (error) {throw new Error(`Failed to read text file at ${filePath}. Error: ${error.message}`);}}/*** 将数据写入文件。** @param fd 已打开的文件描述符。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param options 可选参数:* - offset:写入文件的位置。* - length:写入数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回实际写入的数据长度的 Promise。*/static write(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): Promise<number> {return fs.write(fd, buffer, options).catch((error:BusinessError) => {throw new Error(`Failed to write file data. FD: ${fd}. Error: ${error.message}`);});}/*** 将数据写入文件,以同步方法。** @param fd 已打开的文件描述符。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param options 可选参数:* - offset:写入文件的位置。* - length:写入数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回实际写入的数据长度。*/static writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): number {try {return fs.writeSync(fd, buffer, options);} catch (error) {throw new Error(`Failed to write file data. FD: ${fd}. Error: ${error.message}`);}}/*** 简化写入文件并关闭文件的操作。** @param path 文件的应用沙箱路径。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param append 是否追加写入:* - `true`:追加写入。* - `false`:覆盖写入。* @returns 返回实际写入的数据长度的 Promise。*/static async writeEasy(path: string, buffer: ArrayBuffer | string, append: boolean = true): Promise<number> {const file = await FileUtil.open(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);const offset = append ? (await FileUtil.stat(file.fd)).size : 0;const options: WriteOptions = { offset, encoding: 'utf-8' };const result = await FileUtil.write(file.fd, buffer, options);await FileUtil.close(file.fd);return result;}/*** 关闭文件。** @param file 已打开的文件对象或文件描述符。* @returns 返回一个无返回值的 Promise。*/static close(file: fs.File | number): Promise<void> {return fs.close(file).catch((error:BusinessError) => {throw new Error(`Failed to close file. FD: ${file}. Error: ${error.message}`);});}/*** 关闭文件,以同步方法。** @param file 已打开的文件对象或文件描述符。*/static closeSync(file: fs.File | number): void {try {fs.closeSync(file);} catch (error) {throw new Error(`Failed to close file. FD: ${file}. Error: ${error.message}`);}}/*** 列出文件夹下的所有文件名。** @param path 文件夹的应用沙箱路径。* @param options 文件过滤选项:* - recursion:是否递归子目录。* - listNum:列出文件的数量限制。* - filter:文件过滤规则。* @returns 返回文件名列表的 Promise。*/static listFile(path: string, options?: ListFileOptions): Promise<string[]> {return fs.listFile(path, options).catch((error:BusinessError) => {throw new Error(`Failed to list files in directory at ${path}. Error: ${error.message}`);});}/*** 列出文件夹下的所有文件名,以同步方法。** @param path 文件夹的应用沙箱路径。* @param options 文件过滤选项:* - recursion:是否递归子目录。* - listNum:列出文件的数量限制。* - filter:文件过滤规则。* @returns 返回文件名列表。*/static listFileSync(path: string, options?: ListFileOptions): string[] {try {return fs.listFileSync(path, options);} catch (error) {throw new Error(`Failed to list files in directory at ${path}. Error: ${error.message}`);}}/*** 获取文件详细属性信息。** @param file 文件的应用沙箱路径或文件描述符。* @returns 返回文件状态信息的 Promise。*/static stat(file: string | number): Promise<fs.Stat> {return fs.stat(file).catch((error:BusinessError) => {throw new Error(`Failed to get file stats for ${file}. Error: ${error.message}`);});}/*** 获取文件详细属性信息,以同步方法。** @param file 文件的应用沙箱路径或文件描述符。* @returns 返回文件状态信息。*/static statSync(file: string | number): fs.Stat {try {return fs.statSync(file);} catch (error) {throw new Error(`Failed to get file stats for ${file}. Error: ${error.message}`);}}/*** 拷贝文件或目录,支持进度监听。** @param srcUri 源文件或目录的 URI。* @param destUri 目标文件或目录的 URI。* @param options 可选参数,支持拷贝进度监听。* @returns 返回一个无返回值的 Promise。*/static copy(srcUri: string, destUri: string, options?: fs.CopyOptions): Promise<void> {return fs.copy(srcUri, destUri, options).catch((error:BusinessError) => {throw new Error(`Failed to copy from ${srcUri} to ${destUri}. Error: ${error.message}`);});}/*** 复制文件。** @param src 源文件的路径或文件描述符。* @param dest 目标文件的路径或文件描述符。* @param mode 覆盖文件的选项,默认为完全覆盖。* @returns 返回一个无返回值的 Promise。*/static copyFile(src: string | number, dest: string | number, mode: number = 0): Promise<void> {return fs.copyFile(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to copy file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 复制文件,以同步方法。** @param src 源文件的路径或文件描述符。* @param dest 目标文件的路径或文件描述符。* @param mode 覆盖文件的选项,默认为完全覆盖。*/static copyFileSync(src: string | number, dest: string | number, mode: number = 0): void {try {fs.copyFileSync(src, dest, mode);} catch (error) {throw new Error(`Failed to copy file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 复制源文件夹至目标路径下,只能复制沙箱里的文件夹。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 复制模式:* - `0`:文件级别抛异常。* - `1`:文件级别强制覆盖。* @returns 返回一个无返回值的 Promise。*/static copyDir(src: string, dest: string, mode: number = 1): Promise<void> {return fs.copyDir(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to copy directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 以同步方法复制源文件夹至目标路径下,只能复制沙箱里的文件夹。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 复制模式:* - `0`:文件级别抛异常。* - `1`:文件级别强制覆盖。*/static copyDirSync(src: string, dest: string, mode: number = 1): void {try {fs.copyDirSync(src, dest, mode);} catch (error) {throw new Error(`Failed to copy directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 移动文件,使用 Promise 异步回调。** @param src 源文件的应用沙箱路径。* @param dest 目的文件的应用沙箱路径。* @param mode 移动模式:* - `0`:强制移动覆盖。* - `1`:抛出异常。* @returns 返回一个无返回值的 Promise。*/static moveFile(src: string, dest: string, mode: number = 0): Promise<void> {return fs.moveFile(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to move file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 移动文件,以同步方法。** @param src 源文件的应用沙箱路径。* @param dest 目的文件的应用沙箱路径。* @param mode 移动模式:* - `0`:强制移动覆盖。* - `1`:抛出异常。*/static moveFileSync(src: string, dest: string, mode: number = 0): void {try {fs.moveFileSync(src, dest, mode);} catch (error) {throw new Error(`Failed to move file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 移动源文件夹至目标路径下,使用 Promise 异步返回。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 移动模式:* - `0`:文件夹级别抛异常。* - `1`:文件级别抛异常。* - `2`:文件级别强制覆盖。* - `3`:文件夹级别强制覆盖。* @returns 返回一个无返回值的 Promise。*/static moveDir(src: string, dest: string, mode: number = 3): Promise<void> {return fs.moveDir(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to move directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 以同步方法移动源文件夹至目标路径下。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 移动模式:* - `0`:文件夹级别抛异常。* - `1`:文件级别抛异常。* - `2`:文件级别强制覆盖。* - `3`:文件夹级别强制覆盖。*/static moveDirSync(src: string, dest: string, mode: number = 3): void {try {fs.moveDirSync(src, dest, mode);} catch (error) {throw new Error(`Failed to move directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 截断文件,使用 Promise 异步回调。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @param len 文件截断后的长度(以字节为单位)。* @returns 返回一个无返回值的 Promise。*/static truncate(file: string | number, len: number = 0): Promise<void> {return fs.truncate(file, len).catch((error:BusinessError) => {throw new Error(`Failed to truncate file. Length: ${len}. Error: ${error.message}`);});}/*** 截断文件,以同步方法。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @param len 文件截断后的长度(以字节为单位)。*/static truncateSync(file: string | number, len: number = 0): void {try {fs.truncateSync(file, len);} catch (error) {throw new Error(`Failed to truncate file. Length: ${len}. Error: ${error.message}`);}}/*** 获取链接文件信息,使用 Promise 异步回调。** @param path 文件的应用沙箱路径。* @returns 返回文件的状态信息。*/static lstat(path: string): Promise<fs.Stat> {return fs.lstat(path).catch((error:BusinessError) => {throw new Error(`Failed to get link file info for path: ${path}. Error: ${error.message}`);});}/*** 获取链接文件信息,以同步方法。** @param path 文件的应用沙箱路径。* @returns 返回文件的状态信息。*/static lstatSync(path: string): fs.Stat {try {return fs.lstatSync(path);} catch (error) {throw new Error(`Failed to get link file info for path: ${path}. Error: ${error.message}`);}}/*** 同步文件数据,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @returns 返回一个无返回值的 Promise。*/static fsync(fd: number): Promise<void> {return fs.fsync(fd).catch((error:BusinessError) => {throw new Error(`Failed to sync file data for descriptor: ${fd}. Error: ${error.message}`);});}/*** 同步文件数据,以同步方法。** @param fd 已打开的文件描述符。*/static fsyncSync(fd: number): void {try {fs.fsyncSync(fd);} catch (error) {throw new Error(`Failed to sync file data for descriptor: ${fd}. Error: ${error.message}`);}}/*** 实现文件内容数据同步,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @returns 返回一个无返回值的 Promise。*/static fdatasync(fd: number): Promise<void> {return fs.fdatasync(fd).catch((error:BusinessError) => {throw new Error(`Failed to sync file content data for descriptor: ${fd}. Error: ${error.message}`);});}/*** 实现文件内容数据同步,以同步方法。** @param fd 已打开的文件描述符。*/static fdatasyncSync(fd: number): void {try {fs.fdatasyncSync(fd);} catch (error) {throw new Error(`Failed to sync file content data for descriptor: ${fd}. Error: ${error.message}`);}}/*** 基于文件路径打开文件流,使用 Promise 异步回调。** @param path 文件的应用沙箱路径。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static createStream(path: string, mode: string = 'r'): Promise<fs.Stream> {return fs.createStream(path, mode).catch((error:BusinessError) => {throw new Error(`Failed to create stream for file: ${path}. Mode: ${mode}. Error: ${error.message}`);});}/*** 基于文件路径打开文件流,以同步方法。** @param path 文件的应用沙箱路径。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static createStreamSync(path: string, mode: string = 'r'): fs.Stream {try {return fs.createStreamSync(path, mode);} catch (error) {throw new Error(`Failed to create stream for file: ${path}. Mode: ${mode}. Error: ${error.message}`);}}/*** 基于文件描述符打开文件流,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static fdopenStream(fd: number, mode: string = 'r'): Promise<fs.Stream> {return fs.fdopenStream(fd, mode).catch((error:BusinessError) => {throw new Error(`Failed to open stream for descriptor: ${fd}. Mode: ${mode}. Error: ${error.message}`);});}/*** 基于文件描述符打开文件流,以同步方法。** @param fd 已打开的文件描述符。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static fdopenStreamSync(fd: number, mode: string = 'r'): fs.Stream {try {return fs.fdopenStreamSync(fd, mode);} catch (error) {throw new Error(`Failed to open stream for descriptor: ${fd}. Mode: ${mode}. Error: ${error.message}`);}}/*** 创建临时目录,使用 Promise 异步回调。** @param prefix 用随机产生的字符串替换以“XXXXXX”结尾的目录路径。* @returns 返回创建的临时目录路径。*/static mkdtemp(prefix: string): Promise<string> {return fs.mkdtemp(prefix);}/*** 创建临时目录,以同步的方法。** @param prefix 用随机产生的字符串替换以“XXXXXX”结尾的目录路径。* @returns 返回创建的临时目录路径。*/static mkdtempSync(prefix: string): string {return fs.mkdtempSync(prefix);}/*** 将文件描述符转化为 File。** @param fd 文件描述符。* @returns 返回对应的 File 对象。*/static dup(fd: number): fs.File {return fs.dup(fd);}/*** 修改文件最近访问时间属性。** @param path 文件的应用沙箱路径。* @param mtime 待更新的时间戳(自 1970 年 1 月 1 日起至目标时间的毫秒数)。*/static utimes(path: string, mtime: number): void {try {fs.utimes(path, mtime);} catch (error) {throw new Error(`Failed to update file access time for path: ${path}. Error: ${error.message}`);}}/*** 格式化文件大小为人类可读的格式。** @param fileSize 文件大小(单位:字节)。* @returns 返回格式化后的文件大小字符串(如 "1.2 KB")。*/static getFormatFileSize(fileSize: number): string {if (fileSize < 1024) {return `${fileSize} B`;} else if (fileSize < 1024 * 1024) {return `${(fileSize / 1024).toFixed(1)} KB`;} else if (fileSize < 1024 * 1024 * 1024) {return `${(fileSize / (1024 * 1024)).toFixed(1)} MB`;} else if (fileSize < 1024 * 1024 * 1024 * 1024) {return `${(fileSize / (1024 * 1024 * 1024)).toFixed(1)} GB`;} else {return `${(fileSize / (1024 * 1024 * 1024 * 1024)).toFixed(1)} TB`;}}/*** 构建 PolicyInfo 数组。** @param uris 需要授予或使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 返回 PolicyInfo 数组。*/private static buildPolicyInfos(uris: Array<string>, operationMode: number): Array<fileShare.PolicyInfo> {const policies: Array<fileShare.PolicyInfo> = [];for (const uri of uris) {policies.push({ uri, operationMode });}return policies;}/*** 对所选择的多个文件或目录 URI 持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要授予或使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async persistPermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.persistPermission(policies);}/*** 对所选择的多个文件或目录 URI 持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async persistPermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.persistPermission(policies);}/*** 对所选择的多个文件或目录 URI 取消持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要取消权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async revokePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.revokePermission(policies);}/*** 对所选择的多个文件或目录 URI 取消持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async revokePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.revokePermission(policies);}/*** 对已经持久化授权的权限进行使能操作。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async activatePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.activatePermission(policies);}/*** 对已经持久化授权的权限进行使能操作。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async activatePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.activatePermission(policies);}/*** 取消使能授权过的多个文件或目录。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要取消使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async deactivatePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.deactivatePermission(policies);}/*** 取消使能授权过的多个文件或目录。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async deactivatePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.deactivatePermission(policies);}/*** 校验所选择的多个文件或目录 URI 的持久化授权状态。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 返回布尔值数组,表示每个 URI 是否具有持久化授权。*/static async checkPersistentPermission(policies: Array<fileShare.PolicyInfo>): Promise<Array<boolean>> {return fileShare.checkPersistentPermission(policies);}
}代码如下:
import fileUri from '@ohos.file.fileuri';
import fs, { ListFileOptions, ReadOptions, ReadTextOptions, WriteOptions } from '@ohos.file.fs';
import { StrUtil } from './StrUtil';
import { fileShare } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';/*** 文件操作相关工具类** @author 鸿蒙布道师* @since 2025/04/07*/
export class FileUtil {static readonly separator: string = '/'; // 文件路径分隔符/*** 获取文件目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getFilesDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().filesDir : getContext().getApplicationContext().filesDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 获取缓存目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getCacheDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().cacheDir : getContext().getApplicationContext().cacheDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 获取临时目录下的文件夹路径或文件路径。** @param dirPath 文件路径;支持完整路径和相对路径(如 `download/wps/doc`);传空字符串表示根目录。* @param fileName 文件名(如 `test.text`);传空字符串表示文件夹路径。* @param blHap 是否为 HAP 级别文件路径:* - `true`:HAP 级别文件路径。* - `false`:App 级别文件路径。* @returns 返回完整的文件路径。*/static getTempDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {let filePath = blHap ? getContext().tempDir : getContext().getApplicationContext().tempDir; // 根目录return FileUtil.buildFilePath(filePath, dirPath, fileName);}/*** 构建文件路径的通用逻辑。** @param rootPath 根目录路径。* @param dirPath 子目录路径。* @param fileName 文件名。* @returns 返回完整的文件路径。*/private static buildFilePath(rootPath: string, dirPath: string, fileName: string): string {let filePath = rootPath;if (StrUtil.isNotEmpty(dirPath)) {if (FileUtil.hasDirPath(dirPath)) { // 路径中包含根目录,是完整路径。filePath = dirPath;} else { // 路径中不包含根目录,拼接成完整路径。filePath = `${filePath}${FileUtil.separator}${dirPath}`;}if (!FileUtil.accessSync(filePath)) {FileUtil.mkdirSync(filePath); // 如果文件夹不存在就创建。}}if (StrUtil.isNotEmpty(fileName)) {filePath = `${filePath}${FileUtil.separator}${fileName}`;}return filePath;}/*** 判断是否是完整路径。** @param path 文件路径。* @returns 返回布尔值,表示是否是完整路径。*/static hasDirPath(path: string): boolean {return StrUtil.startsWith(path, "/data/storage/") || StrUtil.startsWith(path, "/storage/");}/*** 通过 URI 或路径,获取 FileUri 对象。** @param uriOrPath URI 或路径。* @returns 返回 FileUri 对象。*/static getFileUri(uriOrPath: string): fileUri.FileUri {return new fileUri.FileUri(uriOrPath);}/*** 通过 URI 或路径,获取文件名。** @param uriOrPath URI 或路径。* @returns 返回文件名。*/static getFileName(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).name;}/*** 通过 URI 或路径,获取文件路径。** @param uriOrPath URI 或路径。* @returns 返回文件路径。*/static getFilePath(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).path;}/*** 通过 URI 或路径,获取对应文件父目录的 URI。** @param uriOrPath URI 或路径。* @returns 返回父目录的 URI。*/static getParentUri(uriOrPath: string): string {return FileUtil.getFileUri(uriOrPath).getFullDirectoryUri();}/*** 通过 URI 或路径,获取对应文件父目录的路径名。** @param uriOrPath URI 或路径。* @returns 返回父目录的路径名。*/static getParentPath(uriOrPath: string): string {const parentUri = FileUtil.getParentUri(uriOrPath);return FileUtil.getFilePath(parentUri);}/*** 以同步方法获取文件 URI。** @param path 应用沙箱路径。* @returns 返回文件 URI。*/static getUriFromPath(path: string): string {return fileUri.getUriFromPath(path);}/*** 根据文件名获取文件后缀。** @param fileName 文件名(如 `test.txt` 或 `test.doc`)。* @returns 返回文件后缀(如 `txt` 或 `doc`)。*/static getFileExtension(fileName: string): string {if (StrUtil.isNotEmpty(fileName) && fileName.includes(".")) {return fileName.substring(fileName.lastIndexOf(".") + 1);}return '';}/*** 获取指定文件夹下所有文件的大小或指定文件的大小。** @param path 文件夹路径或文件路径。* @returns 返回文件或文件夹的总大小(单位:字节)。*/static getFileDirSize(path: string): number {if (!FileUtil.accessSync(path)) {return 0; // 路径不存在时返回 0。}if (FileUtil.isDirectory(path)) { // 文件夹let totalSize = 0;FileUtil.listFileSync(path, { recursion: true }).forEach((filePath) => {try {totalSize += FileUtil.statSync(filePath).size;} catch (error) {console.warn(`Failed to get size for file ${filePath}. Error: ${error.message}`);}});return totalSize;} else { // 文件return FileUtil.statSync(path).size;}}/*** 判断文件是否是普通文件。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @returns 返回布尔值,表示是否是普通文件。*/static isFile(file: string | number): boolean {try {return fs.statSync(file).isFile();} catch (error) {throw new Error(`Failed to check if file is a regular file. Path/FD: ${file}. Error: ${error.message}`);}}/*** 判断文件是否是目录。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @returns 返回布尔值,表示是否是目录。*/static isDirectory(file: string | number): boolean {try {return fs.statSync(file).isDirectory();} catch (error) {throw new Error(`Failed to check if file is a directory. Path/FD: ${file}. Error: ${error.message}`);}}/*** 重命名文件或文件夹,使用 Promise 异步回调。** @param oldPath 文件的应用沙箱原路径。* @param newPath 文件的应用沙箱新路径。* @returns 返回一个无返回值的 Promise。*/static rename(oldPath: string, newPath: string): Promise<void> {return fs.rename(oldPath, newPath).catch((error:BusinessError) => {throw new Error(`Failed to rename file/directory from ${oldPath} to ${newPath}. Error: ${error.message}`);});}/*** 重命名文件或文件夹,以同步方法。** @param oldPath 文件的应用沙箱原路径。* @param newPath 文件的应用沙箱新路径。*/static renameSync(oldPath: string, newPath: string): void {try {fs.renameSync(oldPath, newPath);} catch (error) {throw new Error(`Failed to rename file/directory from ${oldPath} to ${newPath}. Error: ${error.message}`);}}/*** 创建目录,支持多层级创建。** @param path 目录的应用沙箱路径。* @param recursion 是否多层级创建目录:* - `true`:递归创建多级目录。* - `false`:仅创建单层目录。* @returns 返回一个无返回值的 Promise。*/static mkdir(path: string, recursion: boolean = true): Promise<void> {return fs.mkdir(path, recursion).catch((error:BusinessError) => {throw new Error(`Failed to create directory at ${path}. Recursion: ${recursion}. Error: ${error.message}`);});}/*** 创建目录,以同步方法,支持多层级创建。** @param path 目录的应用沙箱路径。* @param recursion 是否多层级创建目录:* - `true`:递归创建多级目录。* - `false`:仅创建单层目录。*/static mkdirSync(path: string, recursion: boolean = true): void {try {fs.mkdirSync(path, recursion);} catch (error) {throw new Error(`Failed to create directory at ${path}. Recursion: ${recursion}. Error: ${error.message}`);}}/*** 删除整个目录。** @param path 目录的应用沙箱路径。* @returns 返回一个无返回值的 Promise。*/static rmdir(path: string): Promise<void> {return fs.rmdir(path).catch((error:BusinessError) => {throw new Error(`Failed to remove directory at ${path}. Error: ${error.message}`);});}/*** 删除整个目录,以同步方法。** @param path 目录的应用沙箱路径。*/static rmdirSync(path: string): void {try {fs.rmdirSync(path);} catch (error) {throw new Error(`Failed to remove directory at ${path}. Error: ${error.message}`);}}/*** 删除单个文件。** @param path 文件的应用沙箱路径。* @returns 返回一个无返回值的 Promise。*/static unlink(path: string): Promise<void> {return fs.unlink(path).catch((error:BusinessError) => {throw new Error(`Failed to delete file at ${path}. Error: ${error.message}`);});}/*** 删除单个文件,以同步方法。** @param path 文件的应用沙箱路径。*/static unlinkSync(path: string): void {try {fs.unlinkSync(path);} catch (error) {throw new Error(`Failed to delete file at ${path}. Error: ${error.message}`);}}/*** 检查文件是否存在。** @param path 文件应用沙箱路径。* @returns 返回一个布尔值的 Promise。*/static access(path: string): Promise<boolean> {return fs.access(path).catch((error:BusinessError) => {throw new Error(`Failed to check file existence at ${path}. Error: ${error.message}`);});}/*** 检查文件是否存在,以同步方法。** @param path 文件应用沙箱路径。* @returns 返回布尔值,表示文件是否存在。*/static accessSync(path: string): boolean {try {return fs.accessSync(path);} catch (error) {throw new Error(`Failed to check file existence at ${path}. Error: ${error.message}`);}}/*** 打开文件,支持使用 URI 打开。** @param path 文件的应用沙箱路径或 URI。* @param mode 打开文件的选项,默认为只读方式打开。* @returns 返回文件对象的 Promise。*/static open(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): Promise<fs.File> {return fs.open(path, mode).catch((error:BusinessError) => {throw new Error(`Failed to open file at ${path}. Mode: ${mode}. Error: ${error.message}`);});}/*** 打开文件,支持使用 URI 打开,以同步方法。** @param path 文件的应用沙箱路径或 URI。* @param mode 打开文件的选项,默认为只读方式打开。* @returns 返回文件对象。*/static openSync(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): fs.File {try {return fs.openSync(path, mode);} catch (error) {throw new Error(`Failed to open file at ${path}. Mode: ${mode}. Error: ${error.message}`);}}/*** 从文件读取数据。** @param fd 已打开的文件描述符。* @param buffer 用于保存读取到的文件数据的缓冲区。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* @returns 返回实际读取的数据长度的 Promise。*/static read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise<number> {return fs.read(fd, buffer, options).catch((error:BusinessError) => {throw new Error(`Failed to read file data. FD: ${fd}. Error: ${error.message}`);});}/*** 从文件读取数据,以同步方法。** @param fd 已打开的文件描述符。* @param buffer 用于保存读取到的文件数据的缓冲区。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* @returns 返回实际读取的数据长度。*/static readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number {try {return fs.readSync(fd, buffer, options);} catch (error) {throw new Error(`Failed to read file data. FD: ${fd}. Error: ${error.message}`);}}/*** 基于文本方式读取文件内容。** @param filePath 文件的应用沙箱路径。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回文件内容的 Promise。*/static readText(filePath: string, options?: ReadTextOptions): Promise<string> {return fs.readText(filePath, options).catch((error:BusinessError) => {throw new Error(`Failed to read text file at ${filePath}. Error: ${error.message}`);});}/*** 基于文本方式读取文件内容,以同步方法。** @param filePath 文件的应用沙箱路径。* @param options 可选参数:* - offset:读取文件的位置。* - length:读取数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回文件内容。*/static readTextSync(filePath: string, options?: ReadTextOptions): string {try {return fs.readTextSync(filePath, options);} catch (error) {throw new Error(`Failed to read text file at ${filePath}. Error: ${error.message}`);}}/*** 将数据写入文件。** @param fd 已打开的文件描述符。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param options 可选参数:* - offset:写入文件的位置。* - length:写入数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回实际写入的数据长度的 Promise。*/static write(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): Promise<number> {return fs.write(fd, buffer, options).catch((error:BusinessError) => {throw new Error(`Failed to write file data. FD: ${fd}. Error: ${error.message}`);});}/*** 将数据写入文件,以同步方法。** @param fd 已打开的文件描述符。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param options 可选参数:* - offset:写入文件的位置。* - length:写入数据的长度。* - encoding:编码方式,默认为 'utf-8'。* @returns 返回实际写入的数据长度。*/static writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): number {try {return fs.writeSync(fd, buffer, options);} catch (error) {throw new Error(`Failed to write file data. FD: ${fd}. Error: ${error.message}`);}}/*** 简化写入文件并关闭文件的操作。** @param path 文件的应用沙箱路径。* @param buffer 待写入文件的数据(可以是缓冲区或字符串)。* @param append 是否追加写入:* - `true`:追加写入。* - `false`:覆盖写入。* @returns 返回实际写入的数据长度的 Promise。*/static async writeEasy(path: string, buffer: ArrayBuffer | string, append: boolean = true): Promise<number> {const file = await FileUtil.open(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);const offset = append ? (await FileUtil.stat(file.fd)).size : 0;const options: WriteOptions = { offset, encoding: 'utf-8' };const result = await FileUtil.write(file.fd, buffer, options);await FileUtil.close(file.fd);return result;}/*** 关闭文件。** @param file 已打开的文件对象或文件描述符。* @returns 返回一个无返回值的 Promise。*/static close(file: fs.File | number): Promise<void> {return fs.close(file).catch((error:BusinessError) => {throw new Error(`Failed to close file. FD: ${file}. Error: ${error.message}`);});}/*** 关闭文件,以同步方法。** @param file 已打开的文件对象或文件描述符。*/static closeSync(file: fs.File | number): void {try {fs.closeSync(file);} catch (error) {throw new Error(`Failed to close file. FD: ${file}. Error: ${error.message}`);}}/*** 列出文件夹下的所有文件名。** @param path 文件夹的应用沙箱路径。* @param options 文件过滤选项:* - recursion:是否递归子目录。* - listNum:列出文件的数量限制。* - filter:文件过滤规则。* @returns 返回文件名列表的 Promise。*/static listFile(path: string, options?: ListFileOptions): Promise<string[]> {return fs.listFile(path, options).catch((error:BusinessError) => {throw new Error(`Failed to list files in directory at ${path}. Error: ${error.message}`);});}/*** 列出文件夹下的所有文件名,以同步方法。** @param path 文件夹的应用沙箱路径。* @param options 文件过滤选项:* - recursion:是否递归子目录。* - listNum:列出文件的数量限制。* - filter:文件过滤规则。* @returns 返回文件名列表。*/static listFileSync(path: string, options?: ListFileOptions): string[] {try {return fs.listFileSync(path, options);} catch (error) {throw new Error(`Failed to list files in directory at ${path}. Error: ${error.message}`);}}/*** 获取文件详细属性信息。** @param file 文件的应用沙箱路径或文件描述符。* @returns 返回文件状态信息的 Promise。*/static stat(file: string | number): Promise<fs.Stat> {return fs.stat(file).catch((error:BusinessError) => {throw new Error(`Failed to get file stats for ${file}. Error: ${error.message}`);});}/*** 获取文件详细属性信息,以同步方法。** @param file 文件的应用沙箱路径或文件描述符。* @returns 返回文件状态信息。*/static statSync(file: string | number): fs.Stat {try {return fs.statSync(file);} catch (error) {throw new Error(`Failed to get file stats for ${file}. Error: ${error.message}`);}}/*** 拷贝文件或目录,支持进度监听。** @param srcUri 源文件或目录的 URI。* @param destUri 目标文件或目录的 URI。* @param options 可选参数,支持拷贝进度监听。* @returns 返回一个无返回值的 Promise。*/static copy(srcUri: string, destUri: string, options?: fs.CopyOptions): Promise<void> {return fs.copy(srcUri, destUri, options).catch((error:BusinessError) => {throw new Error(`Failed to copy from ${srcUri} to ${destUri}. Error: ${error.message}`);});}/*** 复制文件。** @param src 源文件的路径或文件描述符。* @param dest 目标文件的路径或文件描述符。* @param mode 覆盖文件的选项,默认为完全覆盖。* @returns 返回一个无返回值的 Promise。*/static copyFile(src: string | number, dest: string | number, mode: number = 0): Promise<void> {return fs.copyFile(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to copy file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 复制文件,以同步方法。** @param src 源文件的路径或文件描述符。* @param dest 目标文件的路径或文件描述符。* @param mode 覆盖文件的选项,默认为完全覆盖。*/static copyFileSync(src: string | number, dest: string | number, mode: number = 0): void {try {fs.copyFileSync(src, dest, mode);} catch (error) {throw new Error(`Failed to copy file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 复制源文件夹至目标路径下,只能复制沙箱里的文件夹。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 复制模式:* - `0`:文件级别抛异常。* - `1`:文件级别强制覆盖。* @returns 返回一个无返回值的 Promise。*/static copyDir(src: string, dest: string, mode: number = 1): Promise<void> {return fs.copyDir(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to copy directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 以同步方法复制源文件夹至目标路径下,只能复制沙箱里的文件夹。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 复制模式:* - `0`:文件级别抛异常。* - `1`:文件级别强制覆盖。*/static copyDirSync(src: string, dest: string, mode: number = 1): void {try {fs.copyDirSync(src, dest, mode);} catch (error) {throw new Error(`Failed to copy directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 移动文件,使用 Promise 异步回调。** @param src 源文件的应用沙箱路径。* @param dest 目的文件的应用沙箱路径。* @param mode 移动模式:* - `0`:强制移动覆盖。* - `1`:抛出异常。* @returns 返回一个无返回值的 Promise。*/static moveFile(src: string, dest: string, mode: number = 0): Promise<void> {return fs.moveFile(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to move file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 移动文件,以同步方法。** @param src 源文件的应用沙箱路径。* @param dest 目的文件的应用沙箱路径。* @param mode 移动模式:* - `0`:强制移动覆盖。* - `1`:抛出异常。*/static moveFileSync(src: string, dest: string, mode: number = 0): void {try {fs.moveFileSync(src, dest, mode);} catch (error) {throw new Error(`Failed to move file from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 移动源文件夹至目标路径下,使用 Promise 异步返回。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 移动模式:* - `0`:文件夹级别抛异常。* - `1`:文件级别抛异常。* - `2`:文件级别强制覆盖。* - `3`:文件夹级别强制覆盖。* @returns 返回一个无返回值的 Promise。*/static moveDir(src: string, dest: string, mode: number = 3): Promise<void> {return fs.moveDir(src, dest, mode).catch((error:BusinessError) => {throw new Error(`Failed to move directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);});}/*** 以同步方法移动源文件夹至目标路径下。** @param src 源文件夹的应用沙箱路径。* @param dest 目标文件夹的应用沙箱路径。* @param mode 移动模式:* - `0`:文件夹级别抛异常。* - `1`:文件级别抛异常。* - `2`:文件级别强制覆盖。* - `3`:文件夹级别强制覆盖。*/static moveDirSync(src: string, dest: string, mode: number = 3): void {try {fs.moveDirSync(src, dest, mode);} catch (error) {throw new Error(`Failed to move directory from ${src} to ${dest}. Mode: ${mode}. Error: ${error.message}`);}}/*** 截断文件,使用 Promise 异步回调。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @param len 文件截断后的长度(以字节为单位)。* @returns 返回一个无返回值的 Promise。*/static truncate(file: string | number, len: number = 0): Promise<void> {return fs.truncate(file, len).catch((error:BusinessError) => {throw new Error(`Failed to truncate file. Length: ${len}. Error: ${error.message}`);});}/*** 截断文件,以同步方法。** @param file 文件的应用沙箱路径或已打开的文件描述符。* @param len 文件截断后的长度(以字节为单位)。*/static truncateSync(file: string | number, len: number = 0): void {try {fs.truncateSync(file, len);} catch (error) {throw new Error(`Failed to truncate file. Length: ${len}. Error: ${error.message}`);}}/*** 获取链接文件信息,使用 Promise 异步回调。** @param path 文件的应用沙箱路径。* @returns 返回文件的状态信息。*/static lstat(path: string): Promise<fs.Stat> {return fs.lstat(path).catch((error:BusinessError) => {throw new Error(`Failed to get link file info for path: ${path}. Error: ${error.message}`);});}/*** 获取链接文件信息,以同步方法。** @param path 文件的应用沙箱路径。* @returns 返回文件的状态信息。*/static lstatSync(path: string): fs.Stat {try {return fs.lstatSync(path);} catch (error) {throw new Error(`Failed to get link file info for path: ${path}. Error: ${error.message}`);}}/*** 同步文件数据,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @returns 返回一个无返回值的 Promise。*/static fsync(fd: number): Promise<void> {return fs.fsync(fd).catch((error:BusinessError) => {throw new Error(`Failed to sync file data for descriptor: ${fd}. Error: ${error.message}`);});}/*** 同步文件数据,以同步方法。** @param fd 已打开的文件描述符。*/static fsyncSync(fd: number): void {try {fs.fsyncSync(fd);} catch (error) {throw new Error(`Failed to sync file data for descriptor: ${fd}. Error: ${error.message}`);}}/*** 实现文件内容数据同步,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @returns 返回一个无返回值的 Promise。*/static fdatasync(fd: number): Promise<void> {return fs.fdatasync(fd).catch((error:BusinessError) => {throw new Error(`Failed to sync file content data for descriptor: ${fd}. Error: ${error.message}`);});}/*** 实现文件内容数据同步,以同步方法。** @param fd 已打开的文件描述符。*/static fdatasyncSync(fd: number): void {try {fs.fdatasyncSync(fd);} catch (error) {throw new Error(`Failed to sync file content data for descriptor: ${fd}. Error: ${error.message}`);}}/*** 基于文件路径打开文件流,使用 Promise 异步回调。** @param path 文件的应用沙箱路径。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static createStream(path: string, mode: string = 'r'): Promise<fs.Stream> {return fs.createStream(path, mode).catch((error:BusinessError) => {throw new Error(`Failed to create stream for file: ${path}. Mode: ${mode}. Error: ${error.message}`);});}/*** 基于文件路径打开文件流,以同步方法。** @param path 文件的应用沙箱路径。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static createStreamSync(path: string, mode: string = 'r'): fs.Stream {try {return fs.createStreamSync(path, mode);} catch (error) {throw new Error(`Failed to create stream for file: ${path}. Mode: ${mode}. Error: ${error.message}`);}}/*** 基于文件描述符打开文件流,使用 Promise 异步回调。** @param fd 已打开的文件描述符。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static fdopenStream(fd: number, mode: string = 'r'): Promise<fs.Stream> {return fs.fdopenStream(fd, mode).catch((error:BusinessError) => {throw new Error(`Failed to open stream for descriptor: ${fd}. Mode: ${mode}. Error: ${error.message}`);});}/*** 基于文件描述符打开文件流,以同步方法。** @param fd 已打开的文件描述符。* @param mode 文件打开类型。* @returns 返回文件流对象。*/static fdopenStreamSync(fd: number, mode: string = 'r'): fs.Stream {try {return fs.fdopenStreamSync(fd, mode);} catch (error) {throw new Error(`Failed to open stream for descriptor: ${fd}. Mode: ${mode}. Error: ${error.message}`);}}/*** 创建临时目录,使用 Promise 异步回调。** @param prefix 用随机产生的字符串替换以“XXXXXX”结尾的目录路径。* @returns 返回创建的临时目录路径。*/static mkdtemp(prefix: string): Promise<string> {return fs.mkdtemp(prefix);}/*** 创建临时目录,以同步的方法。** @param prefix 用随机产生的字符串替换以“XXXXXX”结尾的目录路径。* @returns 返回创建的临时目录路径。*/static mkdtempSync(prefix: string): string {return fs.mkdtempSync(prefix);}/*** 将文件描述符转化为 File。** @param fd 文件描述符。* @returns 返回对应的 File 对象。*/static dup(fd: number): fs.File {return fs.dup(fd);}/*** 修改文件最近访问时间属性。** @param path 文件的应用沙箱路径。* @param mtime 待更新的时间戳(自 1970 年 1 月 1 日起至目标时间的毫秒数)。*/static utimes(path: string, mtime: number): void {try {fs.utimes(path, mtime);} catch (error) {throw new Error(`Failed to update file access time for path: ${path}. Error: ${error.message}`);}}/*** 格式化文件大小为人类可读的格式。** @param fileSize 文件大小(单位:字节)。* @returns 返回格式化后的文件大小字符串(如 "1.2 KB")。*/static getFormatFileSize(fileSize: number): string {if (fileSize < 1024) {return `${fileSize} B`;} else if (fileSize < 1024 * 1024) {return `${(fileSize / 1024).toFixed(1)} KB`;} else if (fileSize < 1024 * 1024 * 1024) {return `${(fileSize / (1024 * 1024)).toFixed(1)} MB`;} else if (fileSize < 1024 * 1024 * 1024 * 1024) {return `${(fileSize / (1024 * 1024 * 1024)).toFixed(1)} GB`;} else {return `${(fileSize / (1024 * 1024 * 1024 * 1024)).toFixed(1)} TB`;}}/*** 构建 PolicyInfo 数组。** @param uris 需要授予或使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 返回 PolicyInfo 数组。*/private static buildPolicyInfos(uris: Array<string>, operationMode: number): Array<fileShare.PolicyInfo> {const policies: Array<fileShare.PolicyInfo> = [];for (const uri of uris) {policies.push({ uri, operationMode });}return policies;}/*** 对所选择的多个文件或目录 URI 持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要授予或使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async persistPermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.persistPermission(policies);}/*** 对所选择的多个文件或目录 URI 持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async persistPermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.persistPermission(policies);}/*** 对所选择的多个文件或目录 URI 取消持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要取消权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async revokePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.revokePermission(policies);}/*** 对所选择的多个文件或目录 URI 取消持久化授权。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async revokePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.revokePermission(policies);}/*** 对已经持久化授权的权限进行使能操作。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async activatePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.activatePermission(policies);}/*** 对已经持久化授权的权限进行使能操作。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async activatePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.activatePermission(policies);}/*** 取消使能授权过的多个文件或目录。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param uris 需要取消使能权限的 URI 数组。* @param operationMode 授予或使能权限的 URI 访问模式。* @returns 无返回结果的 Promise 对象。*/static async deactivatePermissionEasy(uris: Array<string>,operationMode: number = fileShare.OperationMode.READ_MODE | fileShare.OperationMode.WRITE_MODE): Promise<void> {const policies = FileUtil.buildPolicyInfos(uris, operationMode);await fileShare.deactivatePermission(policies);}/*** 取消使能授权过的多个文件或目录。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 无返回结果的 Promise 对象。*/static async deactivatePermission(policies: Array<fileShare.PolicyInfo>): Promise<void> {await fileShare.deactivatePermission(policies);}/*** 校验所选择的多个文件或目录 URI 的持久化授权状态。(需要权限:ohos.permission.FILE_ACCESS_PERSIST)** @param policies PolicyInfo 数组。* @returns 返回布尔值数组,表示每个 URI 是否具有持久化授权。*/static async checkPersistentPermission(policies: Array<fileShare.PolicyInfo>): Promise<Array<boolean>> {return fileShare.checkPersistentPermission(policies);}
}