查看常用的沙箱目录
应用沙箱文件访问关系图
应用文件目录结构图
查看常用的沙箱目录
@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);
});
选择用户文件
用户有时需要分享或保存图片、视频等用户文件,开发者可以通过系统预置的文件选择器模块来实现(
ohos.file.picker
);根据用户文件的常见类型,选择器模块分别提供以下接口:
PhotoViewPicker
:适用于图片或视频类型文件的选择与保存——图库中的资源;
import { photoAccessHelper } from "@kit.MediaLibraryKit"; //API12
const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
photoViewPicker.select(); //拉起图库界面选择文件
DocumentViewPicker
:适用于文件类型文件的选择与保存——如浏览器下载的文档等;
import { picker } from "@kit.CoreFileKit";
const documentViewPicker = new picker.DocumentViewPicker();
documentViewPicker.select(); //拉起文件选择界面
AudioViewPicker
:适用于音频类型文件的选择与保存。
import { picker } from "@kit.CoreFileKit";
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.select(); //拉起文件选择界面
选择用户文件–选择图片
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%");
选择图库中的图片并上传
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { fileIo } from '@kit.CoreFileKit'
import axios, { AxiosResponse, FormData } from '@ohos/axios'
@Entry
@Component
struct Index {
build() {
Button('读取用户文件 —— 选择图库中的图片并上传').onClick(async _=>{
//拉起图片文件选择器,让用户选择一张图片
let pvp = new photoAccessHelper.PhotoViewPicker()
let result = await pvp.select({
maxSelectNumber: 1,
MIMEType:photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE
})
let path = result.photoUris[0]
console.log('--用户选中的图库文件虚拟路径:', path)
//读取指定路径的文件内容,保存入一个缓冲区
let f = await fileIo.open(path, fileIo.OpenMode.READ_ONLY)
let stat = await fileIo.stat(f.fd) //获取文件的各项统计信息
let size = stat.size //文件大小
let buf = new ArrayBuffer(size) //创建一个与文件大小一样的内存缓冲区对象,用于盛放文件内容
let len = await fileIo.read(f.fd, buf) //读取文件内容
await fileIo.close(f)
console.log('--文件读取完成:',size, len)
//把缓冲区中的数据封装为Multipart/Form-Data格式的请求主体
let body = new FormData()
body.append('avatar', buf)
//使用Axios把请求主体提交给服务器API
let url = 'https://www.**你懂的**.com'
let res: AxiosResponse = await axios({
method:'POST',
url,
headers: {
'Content-Type': 'multipart/form-data',
'token': '加入你自己的token'
},
data: body
})
console.log('--服务器端请求执行完成,响应消息主体数据:', JSON.stringify(res.data))
})
}
}
保存用户文件
在从网络下载文件到本地、或将已有用户文件另存为新的文件路径等场景下,需要使用
ohos.fs.picker
模块提供的保存用户文件的能力。
-
保存图片或视频类型文件:
import { picker } from "@kit.CoreFileKit"; const photoViewPicker = new picker.PhotoViewPicker(); photoViewPicker.save(); //拉起文件选择界面选择文件夹
-
保存文档类文件:
import { picker } from "@kit.CoreFileKit"; const documentViewPicker = new picker.DocumentViewPicker(); documentViewPicker.save(); //拉起文件选择界面选择文件夹
-
保存音频类文件:
import { picker } from "@kit.CoreFileKit"; const audioViewPicker = new picker.AudioViewPicker(); audioViewPicker.save(); //拉起文件选择界面选择文件夹
保存用户文件-网络下载图片
在 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);
});