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

查看常用的沙箱目录


应用沙箱文件访问关系图



应用文件目录结构图


查看常用的沙箱目录

ts 复制代码
@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 组件就看着放就好

写入

ts 复制代码
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

ts 复制代码
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);
});

拷贝

ts 复制代码
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:适用于图片或视频类型文件的选择与保存------图库中的资源;
ts 复制代码
import { photoAccessHelper } from "@kit.MediaLibraryKit"; //API12
const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
photoViewPicker.select(); //拉起图库界面选择文件
  • DocumentViewPicker:适用于文件类型文件的选择与保存------如浏览器下载的文档等;
ts 复制代码
import { picker } from "@kit.CoreFileKit";
const documentViewPicker = new picker.DocumentViewPicker();
documentViewPicker.select(); //拉起文件选择界面
  • AudioViewPicker:适用于音频类型文件的选择与保存。
ts 复制代码
import { picker } from "@kit.CoreFileKit";
const audioViewPicker = new picker.AudioViewPicker();
audioViewPicker.select(); //拉起文件选择界面

选择用户文件--选择图片

ts 复制代码
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%");

选择图库中的图片并上传

ts 复制代码
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 模块提供的保存用户文件的能力。

  • 保存图片或视频类型文件:

    javascript 复制代码
    import { picker } from "@kit.CoreFileKit";
    const photoViewPicker = new picker.PhotoViewPicker();
    photoViewPicker.save(); //拉起文件选择界面选择文件夹
  • 保存文档类文件:

    javascript 复制代码
    import { picker } from "@kit.CoreFileKit";
    const documentViewPicker = new picker.DocumentViewPicker();
    documentViewPicker.save(); //拉起文件选择界面选择文件夹
  • 保存音频类文件:

    javascript 复制代码
    import { picker } from "@kit.CoreFileKit";
    const audioViewPicker = new picker.AudioViewPicker();
    audioViewPicker.save(); //拉起文件选择界面选择文件夹

保存用户文件-网络下载图片

module.json5 文件中声明 网络权限

json 复制代码
"module": {
  "requestPermissions": [   //向系统申请"互联网访问"权限
      {"name": "ohos.permission.INTERNET"}
    ],
}

安装 axios , ohpm install @ohos/axios

ts 复制代码
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);
});
相关推荐
周胡杰5 小时前
组件导航 (HMRouter)+flutter项目搭建-混合开发+分栏效果
前端·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
SuperHeroWu77 小时前
【HarmonyOS 5】鸿蒙星闪NearLink详解
华为·蓝牙·harmonyos·nearlink·鸿蒙星闪·绿牙
积跬步DEV9 小时前
RN 鸿蒙混合开发实践(踩坑)
react native·华为·harmonyos
繁依Fanyi13 小时前
我的 PDF 工具箱:CodeBuddy 打造 PDFMagician 的全过程记录
java·pdf·uni-app·生活·harmonyos·codebuddy首席试玩官
Huang兄13 小时前
#跟着若城学鸿蒙# web篇-获取定位
harmonyos
zkmall15 小时前
Java + 鸿蒙双引擎:ZKmall开源商城如何定义下一代B2C商城技术标准?
java·开源·harmonyos
lqj_本人16 小时前
鸿蒙OS&UniApp实现视频播放与流畅加载:打造完美的移动端视频体验#三方框架 #Uniapp
uni-app·音视频·harmonyos
交叉编译之王 hahaha16 小时前
RK3568平台OpenHarmony系统移植可行性评估
华为·harmonyos
lqj_本人18 小时前
鸿蒙OS&UniApp 实现一个精致的日历组件#三方框架 #Uniapp
uni-app·harmonyos