复制代码
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);
}
}
代码如下:
TypeScript
复制代码
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);
}
}