鸿蒙 Core File Kit(文件基础服务)之简单使用文件
查看常用的沙箱目录
应用沙箱文件访问关系图
应用文件目录结构图
@Entry
@Component
struct Index {build() {Button('查看常用的沙箱目录').onClick(_=>{let ctx = getContext() // UI下只能使用这个方法,不能 this.contextconsole.log('--应用缓存文件保存目录:', ctx.cacheDir)// --应用缓存文件保存目录: /data/storage/el2/base/haps/entry/cacheconsole.log('--应用临时文件保存目录:', ctx.tempDir)// --应用临时文件保存目录: /data/storage/el2/base/haps/entry/tempconsole.log('--应用普通文件保存目录:', ctx.filesDir)// --应用普通文件保存目录: /data/storage/el2/base/haps/entry/filesconsole.log('--应用数据库文件保存目录:', ctx.databaseDir)// --应用数据库文件保存目录: /data/storage/el2/database/entryconsole.log('--应用首选项文件保存目录:', ctx.preferencesDir)// --应用首选项文件保存目录: /data/storage/el2/base/haps/entry/preferencesconsole.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);
});