鸿蒙文件操作完全指南:从基础到实战

更新日期: 2025-11-29 阅读: 30 标签: 鸿蒙

在鸿蒙应用开发中,文件操作是必不可少的功能。无论是保存用户数据、缓存网络资源还是管理应用文件,都需要用到文件系统。今天我们来全面学习鸿蒙中的文件操作api


鸿蒙文件操作基础

鸿蒙提供了两个主要模块来处理文件:

  • @ohos.fileio - 基础文件IO操作

  • @ohos.file.fs - 文件系统高级功能


基础文件操作

检查文件或目录是否存在

在操作文件之前,通常需要先检查文件是否存在。

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

// 检查文件是否存在
function checkFileExists(filePath: string): boolean {
  try {
    const fileStats = fs.statSync(filePath);
    return fileStats.isFile();
  } catch (error) {
    return false;
  }
}

// 检查目录是否存在
function checkDirectoryExists(dirPath: string): boolean {
  try {
    const dirStats = fs.statSync(dirPath);
    return dirStats.isDirectory();
  } catch (error) {
    return false;
  }
}

// 使用示例
const configPath = '/data/storage/el2/base/config.json';
if (checkFileExists(configPath)) {
  console.log('配置文件存在');
} else {
  console.log('配置文件不存在');
}

创建文件和目录

创建文件目录是文件操作的基础。

// 创建单个文件
function createNewFile(filePath: string): boolean {
  try {
    // 打开文件时如果不存在会自动创建
    const fileDescriptor = fs.openSync(filePath, 
      fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
    fs.closeSync(fileDescriptor);
    return true;
  } catch (error) {
    console.error('创建文件失败:', error.message);
    return false;
  }
}

// 创建单个目录
function createNewDirectory(dirPath: string): boolean {
  try {
    fs.mkdirSync(dirPath);
    return true;
  } catch (error) {
    console.error('创建目录失败:', error.message);
    return false;
  }
}

// 递归创建多级目录
function createDirectoriesRecursive(fullPath: string): boolean {
  const parentDir = fileio.dirname(fullPath);
  
  // 如果父目录不存在,先创建父目录
  if (!checkDirectoryExists(parentDir)) {
    createDirectoriesRecursive(parentDir);
  }
  
  return createNewDirectory(fullPath);
}

// 使用示例:创建日志目录
const logDir = '/data/storage/el2/base/logs/app';
if (createDirectoriesRecursive(logDir)) {
  console.log('日志目录创建成功');
}

删除文件和目录

文件清理也是重要的文件操作。

// 删除文件
function removeFile(filePath: string): boolean {
  try {
    fs.unlinkSync(filePath);
    return true;
  } catch (error) {
    console.error('删除文件失败:', error.message);
    return false;
  }
}

// 删除空目录
function removeEmptyDirectory(dirPath: string): boolean {
  try {
    fs.rmdirSync(dirPath);
    return true;
  } catch (error) {
    console.error('删除目录失败:', error.message);
    return false;
  }
}

// 递归删除目录及其所有内容
function removeDirectoryRecursive(dirPath: string): boolean {
  try {
    const files = fs.listFileSync(dirPath);
    
    files.forEach(fileName => {
      const currentPath = `${dirPath}/${fileName}`;
      const stats = fs.statSync(currentPath);
      
      if (stats.isDirectory()) {
        // 如果是目录,递归删除
        removeDirectoryRecursive(currentPath);
      } else {
        // 如果是文件,直接删除
        removeFile(currentPath);
      }
    });
    
    // 删除空目录
    return removeEmptyDirectory(dirPath);
  } catch (error) {
    console.error('递归删除目录失败:', error.message);
    return false;
  }
}


文件读写操作

同步文件读写

同步操作适合处理小文件,代码更简单。

// 同步读取文件内容
function readFileContent(filePath: string): string | null {
  try {
    const fileDescriptor = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
    const fileStats = fs.statSync(filePath);
    
    // 创建缓冲区
    const buffer = new ArrayBuffer(fileStats.size);
    fs.readSync(fileDescriptor, buffer);
    fs.closeSync(fileDescriptor);
    
    // 将二进制数据转换为字符串
    const uint8Array = new Uint8Array(buffer);
    return String.fromCharCode.apply(null, Array.from(uint8Array));
  } catch (error) {
    console.error('读取文件失败:', error.message);
    return null;
  }
}

// 同步写入文件内容
function writeFileContent(filePath: string, content: string): boolean {
  try {
    const fileDescriptor = fs.openSync(filePath, 
      fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
    
    // 将字符串转换为二进制数据
    const buffer = new ArrayBuffer(content.length);
    const uint8Array = new Uint8Array(buffer);
    
    for (let i = 0; i < content.length; i++) {
      uint8Array[i] = content.charCodeAt(i);
    }
    
    fs.writeSync(fileDescriptor, buffer);
    fs.closeSync(fileDescriptor);
    return true;
  } catch (error) {
    console.error('写入文件失败:', error.message);
    return false;
  }
}

// 追加内容到文件
function appendToFile(filePath: string, content: string): boolean {
  try {
    const fileDescriptor = fs.openSync(filePath, 
      fs.OpenMode.READ_WRITE | fs.OpenMode.APPEND);
    
    const buffer = new ArrayBuffer(content.length);
    const uint8Array = new Uint8Array(buffer);
    
    for (let i = 0; i < content.length; i++) {
      uint8Array[i] = content.charCodeAt(i);
    }
    
    fs.writeSync(fileDescriptor, buffer);
    fs.closeSync(fileDescriptor);
    return true;
  } catch (error) {
    console.error('追加文件失败:', error.message);
    return false;
  }
}

// 使用示例:保存用户配置
const userConfig = {
  theme: 'dark',
  language: 'zh-CN',
  notifications: true
};

const configPath = '/data/storage/el2/base/user_config.json';
if (writeFileContent(configPath, JSON.stringify(userConfig))) {
  console.log('用户配置保存成功');
}

异步文件读写

异步操作不会阻塞主线程,适合处理大文件。

// 异步读取文件
async function readFileAsync(filePath: string): Promise<string | null> {
  return new Promise((resolve) => {
    fs.open(filePath, fs.OpenMode.READ_ONLY, (openError, fileDescriptor) => {
      if (openError) {
        console.error('打开文件失败:', openError.message);
        resolve(null);
        return;
      }

      fs.stat(filePath, (statError, fileStats) => {
        if (statError) {
          console.error('获取文件信息失败:', statError.message);
          fs.close(fileDescriptor);
          resolve(null);
          return;
        }

        const buffer = new ArrayBuffer(fileStats.size);
        fs.read(fileDescriptor, buffer, (readError, bytesRead) => {
          fs.close(fileDescriptor);
          
          if (readError) {
            console.error('读取文件失败:', readError.message);
            resolve(null);
            return;
          }
          
          const uint8Array = new Uint8Array(buffer);
          const content = String.fromCharCode.apply(null, Array.from(uint8Array));
          resolve(content);
        });
      });
    });
  });
}

// 异步写入文件
async function writeFileAsync(filePath: string, content: string): Promise<boolean> {
  return new Promise((resolve) => {
    fs.open(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE, 
      (openError, fileDescriptor) => {
        if (openError) {
          console.error('打开文件失败:', openError.message);
          resolve(false);
          return;
        }

        const buffer = new ArrayBuffer(content.length);
        const uint8Array = new Uint8Array(buffer);
        
        for (let i = 0; i < content.length; i++) {
          uint8Array[i] = content.charCodeAt(i);
        }

        fs.write(fileDescriptor, buffer, (writeError, bytesWritten) => {
          fs.close(fileDescriptor);
          
          if (writeError) {
            console.error('写入文件失败:', writeError.message);
            resolve(false);
            return;
          }
          
          resolve(true);
        });
    });
  });
}

// 使用示例:异步读取日志文件
async function displayLogs() {
  const logPath = '/data/storage/el2/base/logs/app.log';
  const logContent = await readFileAsync(logPath);
  
  if (logContent) {
    console.log('日志内容:', logContent);
  } else {
    console.log('读取日志失败');
  }
}

文件流操作

处理大文件时,使用流可以节省内存。

// 创建文件读取流
function createFileReadStream(filePath: string): fileio.Stream | null {
  try {
    return fileio.createStream(filePath, 'r');
  } catch (error) {
    console.error('创建读取流失败:', error.message);
    return null;
  }
}

// 创建文件写入流
function createFileWriteStream(filePath: string): fileio.Stream | null {
  try {
    return fileio.createStream(filePath, 'w');
  } catch (error) {
    console.error('创建写入流失败:', error.message);
    return null;
  }
}

// 使用流复制大文件
async function copyLargeFile(sourcePath: string, targetPath: string): Promise<boolean> {
  return new Promise((resolve) => {
    const readStream = createFileReadStream(sourcePath);
    const writeStream = createFileWriteStream(targetPath);

    if (!readStream || !writeStream) {
      resolve(false);
      return;
    }

    readStream.on('data', (chunk) => {
      writeStream.write(chunk);
    });

    readStream.on('end', () => {
      writeStream.close();
      resolve(true);
    });

    readStream.on('error', (error) => {
      console.error('读取流错误:', error.message);
      writeStream.close();
      resolve(false);
    });

    writeStream.on('error', (error) => {
      console.error('写入流错误:', error.message);
      resolve(false);
    });
  });
}


高级文件操作

文件属性管理

// 获取文件详细信息
function getFileInfo(filePath: string): fs.Stat | null {
  try {
    return fs.statSync(filePath);
  } catch (error) {
    console.error('获取文件信息失败:', error.message);
    return null;
  }
}

// 获取文件大小
function getFileSize(filePath: string): number | null {
  const stats = getFileInfo(filePath);
  return stats ? stats.size : null;
}

// 获取文件修改时间
function getFileModifyTime(filePath: string): number | null {
  const stats = getFileInfo(filePath);
  return stats ? stats.mtime : null;
}

// 修改文件权限
function changeFilePermissions(filePath: string, mode: number): boolean {
  try {
    fs.chmodSync(filePath, mode);
    return true;
  } catch (error) {
    console.error('修改文件权限失败:', error.message);
    return false;
  }
}

路径操作工具

// 获取文件扩展名
function getFileExtension(filePath: string): string {
  const fileName = fileio.basename(filePath);
  const dotIndex = fileName.lastIndexOf('.');
  return dotIndex === -1 ? '' : fileName.slice(dotIndex + 1);
}

// 获取文件名(不含扩展名)
function getFileNameWithoutExtension(filePath: string): string {
  const fileName = fileio.basename(filePath);
  const dotIndex = fileName.lastIndexOf('.');
  return dotIndex === -1 ? fileName : fileName.slice(0, dotIndex);
}

// 安全拼接路径
function joinPathSegments(...segments: string[]): string {
  return segments.join('/').replace(/\/+/g, '/');
}

// 使用示例
const baseDir = '/data/storage/el2/base';
const fileName = 'config.json';
const fullPath = joinPathSegments(baseDir, 'config', fileName);
console.log('完整路径:', fullPath);


实战:文件工具类

下面是一个完整的文件工具类,封装了常用的文件操作。

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

class FileManager {
  // 检查文件是否存在
  static exists(path: string): boolean {
    try {
      fs.statSync(path);
      return true;
    } catch {
      return false;
    }
  }

  // 读取文本文件
  static readTextFile(path: string): string | null {
    try {
      if (!this.exists(path)) {
        return null;
      }

      const fd = fs.openSync(path, fs.OpenMode.READ_ONLY);
      const stats = fs.statSync(path);
      const buffer = new ArrayBuffer(stats.size);
      fs.readSync(fd, buffer);
      fs.closeSync(fd);

      const uint8Array = new Uint8Array(buffer);
      return String.fromCharCode.apply(null, Array.from(uint8Array));
    } catch (error) {
      console.error('读取文件失败:', error.message);
      return null;
    }
  }

  // 写入文本文件
  static writeTextFile(path: string, content: string): boolean {
    try {
      const fd = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
      const buffer = new ArrayBuffer(content.length);
      const uint8Array = new Uint8Array(buffer);
      
      for (let i = 0; i < content.length; i++) {
        uint8Array[i] = content.charCodeAt(i);
      }
      
      fs.writeSync(fd, buffer);
      fs.closeSync(fd);
      return true;
    } catch (error) {
      console.error('写入文件失败:', error.message);
      return false;
    }
  }

  // 读取JSON文件
  static readJSONFile<T>(path: string): T | null {
    const content = this.readTextFile(path);
    if (!content) return null;

    try {
      return JSON.parse(content) as T;
    } catch {
      return null;
    }
  }

  // 写入JSON文件
  static writeJSONFile(path: string, data: any): boolean {
    try {
      const content = JSON.stringify(data, null, 2);
      return this.writeTextFile(path, content);
    } catch (error) {
      console.error('写入JSON文件失败:', error.message);
      return false;
    }
  }

  // 复制文件
  static copyFile(source: string, target: string): boolean {
    try {
      fs.copyFileSync(source, target);
      return true;
    } catch (error) {
      console.error('复制文件失败:', error.message);
      return false;
    }
  }

  // 列出目录内容
  static listDirectory(path: string): string[] | null {
    try {
      return fs.listFileSync(path);
    } catch (error) {
      console.error('列出目录失败:', error.message);
      return null;
    }
  }

  // 创建临时文件
  static createTempFile(prefix: string = 'temp'): string | null {
    try {
      return fs.createTempFileSync(prefix);
    } catch (error) {
      console.error('创建临时文件失败:', error.message);
      return null;
    }
  }
}

// 使用示例
const config = FileManager.readJSONFile<{ theme: string }>('/data/storage/el2/base/config.json');
if (config) {
  console.log('当前主题:', config.theme);
}

// 保存用户数据
const userData = { name: '张三', age: 25 };
FileManager.writeJSONFile('/data/storage/el2/base/userdata.json', userData);


重要注意事项

权限配置

在config.json中声明文件权限:

{
  "module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.READ_MEDIA",
        "reason": "读取用户文件"
      },
      {
        "name": "ohos.permission.WRITE_MEDIA", 
        "reason": "保存用户数据"
      }
    ]
  }
}

性能建议

  1. 小文件:使用同步操作,代码简单

  2. 大文件:使用异步操作或流操作,避免阻塞

  3. 频繁操作:考虑使用缓存减少IO次数

错误处理

所有文件操作都要做好错误处理:

try {
  const content = FileManager.readTextFile('/path/to/file');
  if (content) {
    // 处理文件内容
  }
} catch (error) {
  console.error('文件操作失败:', error.message);
  // 给用户友好的错误提示
}


总结

鸿蒙的文件操作API功能丰富,从基础的文件读写到高级的流操作都有很好的支持。关键是要根据具体场景选择合适的操作方式:

  • 配置文件和用户数据:使用同步读写

  • 日志文件和大文件:使用异步或流操作

  • 临时数据:使用临时文件API

  • 文件管理:使用目录操作API

掌握这些文件操作技巧,你就能在鸿蒙应用中轻松处理各种文件相关的需求了。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/13227

任正非:鸿蒙开源是对全世界小公司创新的支持

鸿蒙系统成为万众瞩目的焦点。华为消费者业务 CEO 余承东曾表示,华为不是要做另一个安卓,鸿蒙要做下一代操作系统,也就是 5G 条件下万物互联的新场景。那么,在复杂环境的影响下

鸿蒙系统中的 JS 开发框架

utils 里面定义了一个 Observer 栈,存放了观察者。subject 定义了被观察者。当我们观察某个对象时,也就是劫持这个对象属性的操作,还包括一些数组函数,比如 push、pop 等。这个文件应该是代码最多的,160 行。observer 的代码就更简单了,五六十行

HarmonyOS(鸿蒙系统)体系

鸿蒙系统(HarmonyOS)是第一款基于微内核的全场景分布式OS,是华为自主研发的操作系统。华为会率先部署在智慧屏、车载终端、穿戴等智能终端上,未来会有越来越多的智能设备使用开源的鸿蒙OS。

HarmonyOS 华为鸿蒙概述

HarmonyOS是一款“面向未来”、面向全场景(移动办公、运动健康、社交通信、媒体娱乐等)的分布式操作系统。在传统的单设备系统能力的基础上,HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念,能够支持多种终端设备

鸿蒙生态下app的四种存在方式

近日,华为正式发布了HarmonyOS 2.0.0,这宣告手机版的鸿蒙操作系统正式到来,很多小伙伴关心手机升级鸿蒙操作系统后,以前的安卓APP还能使用吗?目前,鸿蒙生态下的app会以四种方式存在。

JS语言在HarmonyOS应用开发框架中的作用

在万物互联(Internet of Things,简称IoT)时代,JS(JavaScript)语言越来越重要了,并且受到了很多开发者小伙伴的关注。HarmonyOS也选择JS作为其应用开发的一种语言,肯定有不少好奇的小伙伴想知道:JS语言有什么优势呢?

前端卷鸿蒙?推荐 12 个yyds的开源鸿蒙实战项目

随着鸿蒙操作系统(HarmonyOS)的崛起,华为自主研发的这款操作系统已经吸引了无数关注。本文将分享 12 个开源的鸿蒙实战项目,无论你是鸿蒙领域的新兵,还是经验丰富的老将,希望能从这些项目中获得启发和实用经验

鸿蒙开发实战:HarmonyOS应用内更新详细流程解析

在鸿蒙应用生态中,流畅的更新体验直接影响用户留存。本文将深入解析HarmonyOS应用内更新(In-App Update)的完整实现方案,帮助开发者构建无缝升级体验。

前端新赛道:轻松上手鸿蒙开发

鸿蒙开发并非要取代前端,而是为前端开发者打开一扇新的大门。它像工具箱里新增的一把利器,何时使用,完全取决于你的项目需求与职业机遇。鸿蒙开发为什么值得前端关注

鸿蒙应用开发入门指南

最近很多开发者开始接触鸿蒙应用开发。作为华为推出的操作系统,鸿蒙在开发理念和技术实现上都有自己独特的地方。这篇文章将带你了解鸿蒙开发的核心要点。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!