查看常用的沙箱目录
应用沙箱文件访问关系图
应用文件目录结构图
@Entry
@Component
struct Index {
build() {
Button('查看常用的沙箱目录').onClick(_=>{
let ctx = getContext() // UI下只能使用这个方法,不能 this.context
console.log('--应用缓存文件保存目录:', ctx.cacheDir)
// --应用缓存文件保存目录: /data/storage/el2/base/haps/entry/cache
console.log('--应用临时文件保存目录:', ctx.tempDir)
// --应用临时文件保存目录: /data/storage/el2/base/haps/entry/temp
console.log('--应用普通文件保存目录:', ctx.filesDir)
// --应用普通文件保存目录: /data/storage/el2/base/haps/entry/files
console.log('--应用数据库文件保存目录:', ctx.databaseDir)
// --应用数据库文件保存目录: /data/storage/el2/database/entry
console.log('--应用首选项文件保存目录:', ctx.preferencesDir)
// --应用首选项文件保存目录: /data/storage/el2/base/haps/entry/preferences
console.log('--应用分布式共享文件保存目录:', ctx.distributedFilesDir)
// --应用分布式共享文件保存目录: /data/storage/el2/distributedfiles
})
}
}
DevEco Studio 开发工具右下角有个 Device File Browser,模拟器跑应用的前提下,查看真实的物理目录
data->app->el2->100->base->(项目的 bundleName)->haps->entry(模块名)->files
基础文件操作接口功能
使用 @kit.CoreFileKit
这个 IO
接口
函数名 | 功能描述 | 函数名 | 功能描述 |
---|---|---|---|
access() |
检查文件是否存在 | rmdir() |
删除整个目录 |
close() |
关闭文件 | stat() |
获取文件详细属性信息 |
copyFile() |
复制文件 | unlink() |
删除单个文件 |
createStream() |
打开文件流 | write() |
将数据写入文件 |
listFile() |
列出文件夹下所有文件 | Stream.close() |
关闭文件流 |
mkdir() |
创建目录 | Stream.flush() |
刷新文件流/冲刷缓冲区 |
moveFile() |
移动文件 | Stream.write() |
将数据写入流文件 |
open() |
打开文件 | Stream.read() |
从流文件读取数据 |
read() |
从文件读取数据 | File.fd |
获取文件描述符 |
rename() |
重命名文件 | OpenMode |
设置文件打开标签 |
|
是按位或运算符,用于合并多个互不冲突的选项(标志位),在文件操作中常用于灵活组合打开模式
下面的示例代码注意需要引入的模块,button 组件就看着放就好
写入
Button("2.向应用文件中写出内容 —— 写出日志").onClick(async (_) => {
// 获取应用上下文对象(参考表格外的框架接口)
let ctx = getContext();
// 获取应用沙箱文件目录路径(filesDir为系统预定义路径)
let dir = ctx.filesDir;
// 拼接完整文件路径:目录 + 文件名(参考表格中的`rename()`路径操作逻辑)
let path = dir + "/log01.txt";
// 异步打开文件(对应表格中的`open()`函数)
// path: 文件路径(必须参数)
// OpenMode组合参数(按位或):
// - CREATE: 文件不存在时创建(表格中`mkdir()`的衍生行为)
// - APPEND: 追加写入(避免覆盖原有内容)
// - WRITE_ONLY: 只写模式(与表格中的`read()`互补)
let f = await fileIo.open(
path,
fileIo.OpenMode.CREATE | fileIo.OpenMode.APPEND | fileIo.OpenMode.WRITE_ONLY
);
// 构造日志内容:时间戳 + 固定标记(Date.now()生成13位Unix时间戳)
let str = Date.now() + ":" + "best adc";
// 异步写入文件(对应表格中的`write()`函数)
// f.fd: 文件描述符(来自表格中的`File.fd`属性,标识操作系统级文件句柄)
// str: 要写入的字符串数据(二进制数据需用Buffer转换)
let len = await fileIo.write(f.fd, str);
// 打印日志:len表示实际写入字节数(表格中`write()`的返回值)
console.log(
"--应用文件写出完成,此次写出的数据长度:",
len,
"文件沙箱目录:",
path
);
// 关闭文件(对应表格中的`close()`函数,释放系统资源)
await fileIo.close(f);
});
读取
读取的文件是上个示例创建的 log01.txt
import { buffer } from "@kit.ArkTS";
Button("从应用文件中读取内容 —— 读取日志").onClick(async (_) => {
//指定文件目录和文件名
let ctx = getContext();
let dir = ctx.filesDir;
let path = dir + "/log01.txt";
//打开指定文件,以只读方式
let f = await fileIo.open(path, fileIo.OpenMode.READ_ONLY);
//读取文件内容,保存在一个缓冲区对象中
let buf = new ArrayBuffer(1024); //用于保存读取到的数据的缓冲区
let len = await fileIo.read(f.fd, buf);
console.log("--文件读取完成,实际读取到的字节数:", len);
//把缓冲区中的数据转换为字符串,打印到控制台 —— 前提必需保证缓冲区中的数据是字符数据
let data = buffer.from(buf, 0, len); // 从一个缓冲区对象中构建字符串对象
console.log("--读取到的内容:", data);
//关闭文件
await fileIo.close(f);
});
拷贝
Button("读取并写出应用文件 —— 拷贝日志").onClick(async (_) => {
//指定读取文件 和 写出文件 路径
let ctx = getContext();
let path0 = ctx.filesDir + "/log01.txt"; //源文件——必须存在
let path1 = ctx.filesDir + "/log02.txt"; //目标文件——必须不存在
//打开两个文件
let f0 = await fileIo.open(path0, fileIo.OpenMode.READ_ONLY);
let f1 = await fileIo.open(
path1,
fileIo.OpenMode.CREATE | fileIo.OpenMode.TRUNC | fileIo.OpenMode.WRITE_ONLY
); //如果不存在就创建,否则截断(truncate)已有内容
//从源文件中读取数据,暂放在缓冲区中,写出到目标文件中
let buf = new ArrayBuffer(32); //用于暂存此次读取的数据
let len = 0; //此次实际读取到的字节数
let total = 0; //拷贝的总字节数
while ((len = await fileIo.read(f0.fd, buf)) > 0) {
total += len;
await fileIo.write(f1.fd, buf, { length: len }); //只把缓冲区中指定长度的数据写出
}
console.log("--文件拷贝完成,拷贝的总字节数:", total);
//关闭两个文件
await fileIo.close(f0);
await fileIo.close(f1);
});
选择用户文件–选择图片
import { photoAccessHelper } from "@kit.MediaLibraryKit";
Button("读取用户文件 —— 读取图库中的图片并显式").onClick(async (_) => {
//拉起图片文件拾取窗口,让用户选择文件(本质就是授权应用访问用户文件)
let pvp = new photoAccessHelper.PhotoViewPicker();
// let result = await pvp.select()
let result = await pvp.select({
maxSelectNumber: 1, //一次最多可以选择多少个文件
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, //限定此次只能选择图片文件,不能选择视频文件
});
// console.log('--图片查看拾取器选择的结果:', JSON.stringify(result))
let uri = result.photoUris[0];
console.log("--用户选中的第0个图片的虚拟地址:", uri);
//此后就可以使用fileIo.open(uri)进行文件的读取/拷贝....
this.imgSrc = uri; //还可以直接作为Image的来源进行显式
});
Image(this.imgSrc).width("80%");
保存用户文件-网络下载图片
在 module.json5
文件中声明 网络权限
"module": {
"requestPermissions": [ //向系统申请“互联网访问”权限
{"name": "ohos.permission.INTERNET"}
],
}
安装 axios , ohpm install @ohos/axios
import { fileIo, picker } from "@kit.CoreFileKit";
import axios, { AxiosResponse } from "@ohos/axios";
Button("7.读取用户目录 —— 下载文件到该目录").onClick(async (_) => {
//使用axios请求远程服务器上的图片
let res: AxiosResponse = await axios({
method: "GET",
url: "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
});
console.log(
"--下载图片保存到一个缓冲区对象了: res.data",
JSON.stringify(res)
);
// 拉起文档查看拾取器,选择一个目录用于保存上述文件
let dvp = new picker.DocumentViewPicker();
let result = await dvp.save();
console.log("--文档拾取器选择的目录:", JSON.stringify(result));
let path = result[0]; //往哪个文件中写出下载的图片内容
//往上述目录下写出下载得到的文件数据
let f = await fileIo.open(
path,
fileIo.OpenMode.CREATE | fileIo.OpenMode.TRUNC | fileIo.OpenMode.WRITE_ONLY
);
let len = await fileIo.write(f.fd, res.data);
console.log("--文件保存完成,总大小:", len);
await fileIo.close(f);
});