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

时间:2025-04-07 08:36:39

应用文件访问(ArkTS)
 

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

接口说明

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

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

 

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

 

开发示例

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

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

新建并读写一个文件

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

// pages/
import { fileIo as fs, ReadOptions } from '@';
import { common } from '@';
import { buffer } from '@';

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

function createFile(): void {
  // 新建并打开文件
  let file = (filesDir + '/', .READ_WRITE | );
  // 写入一段内容至文件
  let writeLen = (, "Try to write str.");
  ("The length of str is: " + writeLen);
  // 从文件读取一段内容
  let arrayBuffer = new ArrayBuffer(1024);
  let readOptions: ReadOptions = {
    offset: 0,
    length: 
  };
  let readLen = (, arrayBuffer, readOptions);
  let buf = (arrayBuffer, 0, readLen);
  ("the content of file: " + ());
  // 关闭文件
  (file);
}

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

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

 

// pages/
import { fileIo as fs, ReadOptions, WriteOptions } from '@';
import { common } from '@';

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

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

说明

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

以流的形式读写文件

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

 

// pages/
import { fileIo as fs, ReadOptions } from '@';
import { common } from '@';

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

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

说明

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

 

查看文件列表

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

 

import { fileIo as fs, Filter, ListFileOptions } from '@';
import { common } from '@';

// 获取应用文件路径
let context = getContext(this) as ;
let 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 = (filesDir, listFileOption);
  for (let i = 0; i < ; i++) {
    (`The name of file: ${files[i]}`);
  }
}

使用文件流

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

 

// pages/
import { fileIo as fs } from '@';
import { common } from '@';

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

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

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

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

 

// pages/
import { fileIo as fs } from '@';
import { hash } from '@';
import { common } from '@';

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

function hashFileWithStream() {
  const filePath = `${filesDir}/`;
  // 创建文件可读流
  const rs = (filePath);
  // 创建哈希流
  const hs = ('sha256');
  ('data', (emitData) => {
    const data = emitData?.data;
    (new Uint8Array(data?.split('').map((x: string) => (0))).buffer);
  });
  ('close', async () => {
    const hashResult = ();
    const fileHash = await (filePath, 'sha256');
    (`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脚本中链接动态库

中添加以下lib。

 

target_link_libraries(sample PUBLIC )

添加头文件
 

#include <filemanagement/fileio/oh_fileio.h>

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

 

    void GetFileLocationExample() {
        char *uri = "file:///data/storage/el2/base/files/";
        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的详细介绍请参见

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

模块 接口名 功能
@ getCurrentBundleStats 获取当前应用的存储空间大小(单位为Byte)。
@ getFreeSize 获取指定文件系统的剩余空间大小(单位为Byte)。
@ getTotalSize 获取指定文件系统的总空间大小(单位为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 '@';
    import { BusinessError } from '@';
    import { common } from '@';
    
    let context = getContext(this) as ;
    let path = ;
    (path, (err: BusinessError, number: number) => {
      if (err) {
        (`Invoke getFreeSize failed, code is ${}, message is ${}`);
      } else {
        (`Invoke getFreeSize succeeded, size is ${number}`);
      }
    });
    

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

     

    import { storageStatistics } from '@';
    import { BusinessError } from '@';
    
    ((err: BusinessError, bundleStats: ) => {
      if (err) {
        (`Invoke getCurrentBundleStats failed, code is ${}, message is ${}`);
      } else {
        (`Invoke getCurrentBundleStats succeeded, appsize is ${}`);
      }
    });