鸿蒙 Core File Kit(文件基础服务)之简单使用文件

发布于:2025-05-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

查看常用的沙箱目录

在这里插入图片描述
应用沙箱文件访问关系图


在这里插入图片描述
应用文件目录结构图


@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);
});

网站公告

今日签到

点亮在社区的每一天
去签到