HarmonyOS NEXT - 应用文件访问与管理

应用文件访问(ArkTS)
 

应用需要对应用文件目录下的应用文件进行查看、创建、读写、删除、移动、复制、获取属性等访问操作,下文介绍具体方法。

接口说明

开发者通过基础文件操作接口(ohos.file.fs)实现应用文件访问能力,主要功能如下表所示。

表1 基础文件操作接口功能

 

接口名功能接口类型支持同步支持异步
access检查文件是否存在方法
close关闭文件方法
copyFile复制文件方法
createStream基于文件路径打开文件流方法
listFile列出文件夹下所有文件名方法
mkdir创建目录方法
moveFile移动文件方法
open打开文件方法
read从文件读取数据方法
rename重命名文件或文件夹方法
rmdir删除整个目录方法
stat获取文件详细属性信息方法
unlink删除单个文件方法
write将数据写入文件方法
Stream.close关闭文件流方法
Stream.flush刷新文件流方法
Stream.write将数据写入流文件方法
Stream.read从流文件读取数据方法
File.fd获取文件描述符属性--
OpenMode设置文件打开标签属性--
Filter设置文件过滤配置项类型--

 

开发示例

在对应用文件开始访问前,开发者需要获取应用文件路径。以从UIAbilityContext获取HAP级别的文件路径为例进行说明,UIAbilityContext的获取方式请参见获取UIAbility的上下文信息

下面介绍几种常用操作示例。

新建并读写一个文件

以下示例代码演示了如何新建一个文件并对其读写。

// pages/xxx.ets
import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { buffer } from '@kit.ArkTS';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

function createFile(): void {
  // 新建并打开文件
  let file = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  // 写入一段内容至文件
  let writeLen = fs.writeSync(file.fd, "Try to write str.");
  console.info("The length of str is: " + writeLen);
  // 从文件读取一段内容
  let arrayBuffer = new ArrayBuffer(1024);
  let readOptions: ReadOptions = {
    offset: 0,
    length: arrayBuffer.byteLength
  };
  let readLen = fs.readSync(file.fd, arrayBuffer, readOptions);
  let buf = buffer.from(arrayBuffer, 0, readLen);
  console.info("the content of file: " + buf.toString());
  // 关闭文件
  fs.closeSync(file);
}

读取文件内容并写入到另一个文件

以下示例代码演示了如何从一个文件读写内容到另一个文件。

 

// pages/xxx.ets
import { fileIo as fs, ReadOptions, WriteOptions } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

function readWriteFile(): void {
  // 打开文件
  let srcFile = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  let destFile = fs.openSync(filesDir + '/destFile.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  // 读取源文件内容并写入至目的文件
  let bufSize = 4096;
  let readSize = 0;
  let buf = new ArrayBuffer(bufSize);
  let readOptions: ReadOptions = {
    offset: readSize,
    length: bufSize
  };
  let readLen = fs.readSync(srcFile.fd, buf, readOptions);
  while (readLen > 0) {
    readSize += readLen;
    let writeOptions: WriteOptions = {
      length: readLen
    };
    fs.writeSync(destFile.fd, buf, writeOptions);
    readOptions.offset = readSize;
    readLen = fs.readSync(srcFile.fd, buf, readOptions);
  }
  // 关闭文件
  fs.closeSync(srcFile);
  fs.closeSync(destFile);
}

说明

使用读写接口时,需注意可选项参数offset的设置。对于已存在且读写过的文件,文件偏移指针默认在上次读写操作的终止位置。

以流的形式读写文件

以下示例代码演示了如何使用流接口进行文件读写:

 

// pages/xxx.ets
import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

async function readWriteFileWithStream(): Promise<void> {
  // 打开文件流
  let inputStream = fs.createStreamSync(filesDir + '/test.txt', 'r+');
  let outputStream = fs.createStreamSync(filesDir + '/destFile.txt', "w+");
  // 以流的形式读取源文件内容并写入目的文件
  let bufSize = 4096;
  let readSize = 0;
  let buf = new ArrayBuffer(bufSize);
  let readOptions: ReadOptions = {
    offset: readSize,
    length: bufSize
  };
  let readLen = await inputStream.read(buf, readOptions);
  readSize += readLen;
  while (readLen > 0) {
    const writeBuf = readLen < bufSize ? buf.slice(0, readLen) : buf;
    await outputStream.write(writeBuf);
    readOptions.offset = readSize;
    readLen = await inputStream.read(buf, readOptions);
    readSize += readLen;
  }
  // 关闭文件流
  inputStream.closeSync();
  outputStream.closeSync();
}

说明

使用流接口时,需注意流的及时关闭。同时流的异步接口应严格遵循异步接口使用规范,避免同步、异步接口混用。流接口不支持并发读写。

 

查看文件列表

以下示例代码演示了如何查看文件列表:

 

import { fileIo as fs, Filter, ListFileOptions } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

// 查看文件列表
function getListFile(): void {
  let listFileOption: ListFileOptions = {
    recursion: false,
    listNum: 0,
    filter: {
      suffix: [".png", ".jpg", ".txt"],
      displayName: ["test*"],
      fileSizeOver: 0,
      lastModifiedAfter: new Date(0).getTime()
    }
  };
  let files = fs.listFileSync(filesDir, listFileOption);
  for (let i = 0; i < files.length; i++) {
    console.info(`The name of file: ${files[i]}`);
  }
}

使用文件流

以下实例代码演示了如何使用文件可读流,文件可写流

 

// pages/xxx.ets
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

function copyFileWithReadable(): void {
  // 创建文件可读流
  const rs = fs.createReadStream(`${filesDir}/read.txt`);
  // 创建文件可写流
  const ws = fs.createWriteStream(`${filesDir}/write.txt`);
  // 暂停模式拷贝文件
  rs.on('readable', () => {
    const data = rs.read();
    if (!data) {
      return;
    }
    ws.write(data);
  });
}

function copyFileWithData(): void {
  // 创建文件可读流
  const rs = fs.createReadStream(`${filesDir}/read.txt`);
  // 创建文件可写流
  const ws = fs.createWriteStream(`${filesDir}/write.txt`);
  // 流动模式拷贝文件
  rs.on('data', (emitData) => {
    const data = emitData?.data;
    if (!data) {
      return;
    }
    ws.write(data as Uint8Array);
  });
}

以下代码演示了如何使用文件哈希流

 

// pages/xxx.ets
import { fileIo as fs } from '@kit.CoreFileKit';
import { hash } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

function hashFileWithStream() {
  const filePath = `${filesDir}/test.txt`;
  // 创建文件可读流
  const rs = fs.createReadStream(filePath);
  // 创建哈希流
  const hs = hash.createHash('sha256');
  rs.on('data', (emitData) => {
    const data = emitData?.data;
    hs.update(new Uint8Array(data?.split('').map((x: string) => x.charCodeAt(0))).buffer);
  });
  rs.on('close', async () => {
    const hashResult = hs.digest();
    const fileHash = await hash.hash(filePath, 'sha256');
    console.info(`hashResult: ${hashResult}, fileHash: ${fileHash}`);
  });
}

应用文件访问(C/C++)

 

场景介绍

FileIO模块提供了文件基础操作能力。

基本概念

结果集:满足使用场景正确的 URI。

约束限制

  • 进行文件操作之前,必须保证传入正确有效的uri或path。

接口说明

接口的详细说明,请参考



API参考


 

接口名称描述
FileManagement_ErrCode OH_FileIO_GetFileLocation(char *uri, int uriLength, FileIO_FileLocation *location)获取文件存储位置。
enum FileIO_FileLocation FileIO_FileLocation文件存储位置枚举值。
enum enum FileManagement_ErrCode FileManagement_ErrCode文件管理模块错误码。

开发步骤

在CMake脚本中链接动态库

CMakeLists.txt中添加以下lib。

 

target_link_libraries(sample PUBLIC libohfileio.so)

添加头文件
 

#include <filemanagement/fileio/oh_fileio.h>

调用OH_FileIO_GetFileLocation接口获取文件存储位置。示例代码如下所示:

 

    void GetFileLocationExample() {
        char *uri = "file://com.example.demo/data/storage/el2/base/files/test.txt";
        FileIO_FileLocation location;
        FileManagement_ErrCode ret = OH_FileIO_GetFileLocation(uri, strlen(uri), &location);
        if (ret == 0) {
            if (location == FileIO_FileLocation::LOCAL) {
                printf("This file is on local.");
            } else if (location == FileIO_FileLocation::CLOUD) {
                printf("This file is on cloud.");
            } else if (location == FileIO_FileLocation::LOCAL_AND_CLOUD) {
                printf("This file is both on local and cloud.");
            }
        } else {
            printf("GetFileLocation failed, error code is %d", ret);
        }
    }    


应用及文件系统空间统计

 

在系统中,可能出现系统空间不够或者cacheDir等目录受系统配额限制等情况,需要应用开发者关注系统剩余空间,同时控制应用自身占用的空间大小。

接口说明

API的详细介绍请参见ohos.file.statvfsohos.file.storageStatistics

表1 文件系统空间和应用空间统计

模块接口名功能
@ohos.file.storageStatisticsgetCurrentBundleStats获取当前应用的存储空间大小(单位为Byte)。
@ohos.file.statvfsgetFreeSize获取指定文件系统的剩余空间大小(单位为Byte)。
@ohos.file.statvfsgetTotalSize获取指定文件系统的总空间大小(单位为Byte)。

表2 应用空间统计

BundleStats属性含义统计路径
appSize应用安装文件大小(单位为Byte)

应用安装文件保存在以下目录:

/data/storage/el1/bundle

cacheSize应用缓存文件大小(单位为Byte)

应用的缓存文件保存在以下目录:

/data/storage/el1/base/cache

/data/storage/el1/base/haps/entry/cache

/data/storage/el2/base/cache

/data/storage/el2/base/haps/entry/cache

dataSize应用文件存储大小(除应用安装文件和缓存文件)(单位为Byte)

应用文件由本地文件、分布式文件以及数据库文件组成。

本地文件保存在以下目录(注意缓存文件目录为以下目录的子目录):

/data/storage/el1/base

/data/storage/el2/base

分布式文件保存在以下目录:

/data/storage/el2/distributedfiles

数据库文件保存在以下目录:

/data/storage/el1/database

/data/storage/el2/database

开发示例

  • 获取文件系统数据分区剩余空间大小。

     

    import { statfs } from '@kit.CoreFileKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { common } from '@kit.AbilityKit';
    
    let context = getContext(this) as common.UIAbilityContext;
    let path = context.filesDir;
    statfs.getFreeSize(path, (err: BusinessError, number: number) => {
      if (err) {
        console.error(`Invoke getFreeSize failed, code is ${err.code}, message is ${err.message}`);
      } else {
        console.info(`Invoke getFreeSize succeeded, size is ${number}`);
      }
    });
    

    获取当前应用的存储空间大小。

     

    import { storageStatistics } from '@kit.CoreFileKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    storageStatistics.getCurrentBundleStats((err: BusinessError, bundleStats: storageStatistics.BundleStats) => {
      if (err) {
        console.error(`Invoke getCurrentBundleStats failed, code is ${err.code}, message is ${err.message}`);
      } else {
        console.info(`Invoke getCurrentBundleStats succeeded, appsize is ${bundleStats.appSize}`);
      }
    });
    

  • 24
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值