应用文件访问(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 ${}`); } });