鸿蒙中的文件读写操作分析

66 阅读2分钟

在鸿蒙系统中,可用对文件进行创建、打开、读取、写入等操作,本文通过代码示例进行分析。 首先通过import进行模块导入,模块是一段可重用的代码,它将相关的功能、类、函数等组织在一起一个文件中。

import fs from '@ohos.file.fs'
import common from '@ohos.app.ability.common'
import { BusinessError } from '@ohos.base'
import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl'

另外,在鸿蒙系统中,应用的安装位置和目录结构会根据系统版本和应用类型有所不同。
对于系统应用(System Apps)而言,其路径是:
/system/app/[应用包名]/
/system/priv-app/[应用包名]/ (系统特权应用)
对于第三方应用(Third-party Apps)而言,其路径是:
/data/app/el2/[用户ID]/base/[应用包名]/
比如: /data/app/el2/100/base/com.example.myapp/
可以将一个文件推送到设备中应用所在的路径下,
hdc file send .\test.txt /data/app/el2/100/base/com.example.myapp/haps/entry/files

1,获取文件路径

mContext: common.UIAbilityContext | null = null;
initContext(context: common.UIAbilityContext): void {
    this.mContext = context;
}
async getFilePath(): Promise<string> {
	const fileDir = this.mContext.filesDir // 路径是:/data/storage/el2/base/haps/entry/files/
	const fileName = "test.txt"
	const filePath = fileDir.endsWith('/') ? fileDir + fileName : fileDir + '/' + fileName;
	return filePath.trim()
}

2,打开或创建文件

async openContent(filePath: string) {
	let fileFd = 0
    let file: fs.File | null = null;
	try {
      // 传入的路径是/data/storage/el2/base/haps/entry/files/时就可以打开通过hdc推送到设备中的test.txt文件。
      file = await fs.open(filePath, fs.OpenMode.READ_ONLY);
      fileFd = file.fd;
    } catch (error) {
      const err = error as BusinessError
      console.log(`openContent:fs.open failed: ${filePath}, errCode: ${err.code}, errMsg: ${err.message}`)
      console.log("openContent:try to create file");
      try {
        file = await fs.open(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
        fileFd = file.fd
        if (!filePath || typeof filePath !== 'string') {
          console.log("openContent:invalidate path");
        }
      } catch (err) {
        const error = err as BusinessError
        console.log(`openContent:fs.open failed: ${filePath}, errCode: ${error.code}, errMsg: ${error.message}`)
      } finally {
		fs.closeSync(fileFd);
	  }
    }
}

3,写文件内容

async writeContent(filePath: string) {
	const devices = [];
    for (let i = 0; i <= 10; i++) {
      devices.push({
        name: `device ${i}`,
        ip: `192.168.0.${101 + i}`
      });
    }
	const devData = "testdata": devices
	const devDataJsonStr = JSON.stringify(devData, null, 2); // JSON.stringify()将 JavaScript 对象转换为 JSON 字符串,使用 2 个空格缩进(格式化输出)。
	const jsonStr = devDataJsonStr.replace(/\n/g, '');
	console.log("JSON string,jsonStr:", jsonStr);
	let fileFd = 0
	try {
      const file = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      fileFd = file.fd
      const writedContent = devDataJsonStr
      fs.writeSync(fileFd, writedContent)
    } catch (e) {
      const err = e as BusinessError
      console.log(`writeContent:writeSync failed: ${filePath}, errCode: ${err.code}, errMsg: ${err.message}`)
    } finally {
      fs.closeSync(fileFd);
    }
}

4,读文件内容

async readContent(filePath: string): Promise<string | null> {
	try {
      const bufferSize = 4096;
      let totalBuffer = new Uint8Array(0);
      let readLen: number;
      let content = '';
	  let fileFd = await fs.openSync(filePath, fs.OpenMode.READ_ONLY).fd
      do {
        const buffer = new ArrayBuffer(bufferSize);
        readLen = fs.readSync(fileFd, buffer);
        if (readLen > 0) {
          const currentBuffer = new Uint8Array(buffer.slice(0, readLen));
          const newBuffer  = new Uint8Array(totalBuffer.length + readLen);
          newBuffer .set(totalBuffer, 0);
          newBuffer .set(currentBuffer, totalBuffer.length);
          totalBuffer = newBuffer ;
        }
      } while (readLen > 0);
      for (let i = 0; i < totalBuffer.length; i++) {
        content += String.fromCharCode(totalBuffer[i]);
      }
      const retContent = content.replace(/\n/g, '');
      console.log("readContent:read content success:", retContent);
      return retContent
    } catch (error) {
      const err = error as BusinessError
      console.log(`readContent:readSync failed: ${filePath}, errCode: ${err.code}, errMsg: ${err.message}`)
      return null;
    } finally {
      fs.closeSync(fileFd);
    }
}

5,请求权限

async requestPermission(): Promise<boolean> {
    const TARGET_PERMISSIONS = [
      'ohos.permission.FILE_ACCESS_MANAGER',
      'ohos.permission.READ_MEDIA',
      'ohos.permission.WRITE_MEDIA',
    ] as Permissions[];
    const context = this.mContext

    try {
      const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();

      let allGranted = true;
      const requestResult: PermissionRequestResult = await (atManager.requestPermissionsFromUser(context, TARGET_PERMISSIONS) as Promise<PermissionRequestResult>);
      for (const permission of TARGET_PERMISSIONS) {
        const status = this.getPermissionStatusFromResult(requestResult, permission);
        console.log(`requestPermission:${permission} status:`, status);
        if (await status !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
          console.log(`requestPermission:${permission} set all granted false.`);
          allGranted = false;
        }
      }
      if (allGranted) {
		console.log(`requestPermission:already own permission`);
      }
      return allGranted;
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.log(`requestPermission failed:errCode=${err.code}, errMsg=${err.message}`);
      return false;
    }
}
 
private getPermissionStatusFromResult(
    requestResult: PermissionRequestResult,
    permission: string
  ): abilityAccessCtrl.GrantStatus {
    try {
      // 处理数组格式的结果
      if (Array.isArray(requestResult.permissions)) {
        return requestResult.permissions.includes(permission)
          ? abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED
          : abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
      }
      // 处理对象格式的结果
      if (requestResult.permissions && typeof requestResult.permissions === 'object') {
        const permissionsObj = requestResult.permissions as Record<string, abilityAccessCtrl.GrantStatus>;
        return permissionsObj[permission] ?? abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
      }
      // 默认返回拒绝
      return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
    } catch (error) {
      console.log(`parse permission failed: ${error.message}`);
      return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
    }
}