rawfile 目录文件使用

问题:我在 rawfile 目录创建一个文件,怎么去使用?

回答

rawfile 是鸿蒙中存放原始文件资源的特殊目录,使用 ResourceManager 来访问这些文件。

一、rawfile 目录特点

1. 位置

文件放在项目的resources/rawfile/目录下,可以创建子目录进行分类管理。

2. 文件类型

可以存放任何类型的文件:

  • JSON 配置文件
  • 文本文件(txt、md 等)
  • 图片文件(虽然不推荐)
  • 音频视频文件
  • 字体文件
  • 其他二进制文件
3. 核心特点
  • 文件会被原封不动地打包到应用中,不会被编译或压缩
  • 保持原始文件结构和内容
  • 通过相对路径访问
  • 只读,不能修改

二、访问 rawfile 文件的步骤

步骤 1:获取 ResourceManager

通过 Context 获取 ResourceManager 实例,ResourceManager 是访问应用资源的统一管理器。

// 在组件中获取
const resourceManager = getContext(this).resourceManager;

// 在 UIAbility 中获取
const resourceManager = this.context.resourceManager;
步骤 2:使用 ResourceManager 读取文件

ResourceManager 提供了多种读取方法:

1. getRawFileContent() - 读取文件内容

  • 返回 Uint8Array 字节数组
  • 适合读取完整文件内容
  • 参数是文件的相对路径(相对于 rawfile 目录)

2. getRawFd() - 获取文件描述符

  • 返回 RawFileDescriptor 对象
  • 适合大文件或需要流式读取的场景
  • 包含文件描述符、偏移量、长度信息

3. getRawFileList() - 获取目录下的文件列表

  • 返回指定目录下的所有文件名
  • 用于遍历 rawfile 目录

三、常见使用场景

场景 1:读取 JSON 配置文件

这是最常见的使用场景,比如应用配置、城市列表、分类数据等。

// 读取 rawfile/config.json 文件
async loadConfig() {
  try {
    const resourceManager = getContext(this).resourceManager
    // 读取字节数组
    const fileData = await resourceManager.getRawFileContent('config.json')
    // 转换为字符串
    const jsonStr = new util.TextDecoder('utf-8').decodeWithStream(fileData)
    // 解析为 JSON 对象
    const configObj = JSON.parse(jsonStr)
    console.log('配置数据:', configObj)
  } catch (err) {
    console.error('读取配置文件失败:', err)
  }
}
场景 2:读取文本文件

比如用户协议、隐私政策、帮助文档等。

// 读取 rawfile/docs/agreement.txt 文件
async loadAgreement() {
  try {
    const resourceManager = getContext(this).resourceManager
    const fileData = await resourceManager.getRawFileContent('docs/agreement.txt')
    const textContent = new util.TextDecoder('utf-8').decodeWithStream(fileData)
    // 直接使用文本内容
    this.agreementText = textContent
  } catch (err) {
    console.error('读取文本文件失败:', err)
  }
}
场景 3:读取字体文件

自定义字体需要放在 rawfile 中。

// 在组件样式中使用自定义字体
Text("自定义字体文本").fontFamily($rawfile("fonts/custom.ttf")).fontSize(20);
场景 4:读取多媒体文件

音频、视频等媒体文件。

// 获取音频文件的文件描述符,用于播放器
async playAudio() {
  try {
    const resourceManager = getContext(this).resourceManager
    const fd = await resourceManager.getRawFd('music/background.mp3')
    // 使用文件描述符播放音频
    // avPlayer.fdSrc = fd
  } catch (err) {
    console.error('读取音频文件失败:', err)
  }
}
场景 5:获取目录下的文件列表
// 获取 rawfile/data/ 目录下的所有文件
async getFileList() {
  try {
    const resourceManager = getContext(this).resourceManager
    const fileList = await resourceManager.getRawFileList('data')
    console.log('文件列表:', fileList) // ['users.json', 'config.json']
  } catch (err) {
    console.error('获取文件列表失败:', err)
  }
}

四、与其他资源目录的区别

rawfile vs media 目录

media 目录:

  • 存放图片、音视频等媒体资源
  • 会被系统优化压缩
  • 通过$r(‘app.media.xxx’)访问
  • 有限定的文件类型

rawfile 目录:

  • 存放任意类型的原始文件
  • 不会被压缩或优化
  • 通过 ResourceManager 或$rawfile()访问
  • 保持文件原始状态
使用建议
  • 图片资源优先放 media 目录,系统会优化
  • JSON、文本配置文件放 rawfile
  • 需要保持原始格式的文件放 rawfile
  • 字体文件必须放 rawfile

五、路径规则

基本路径

如果文件在resources/rawfile/config.json,访问路径就是"config.json"

// 正确
resourceManager.getRawFileContent("config.json");

// 错误 - 不需要 rawfile 前缀
resourceManager.getRawFileContent("rawfile/config.json");
子目录路径

如果文件在resources/rawfile/data/users.json,访问路径就是"data/users.json"

// 正确 - 使用相对路径
resourceManager.getRawFileContent("data/users.json");

// 子目录中的文件
resourceManager.getRawFileContent("images/icons/logo.png");
resourceManager.getRawFileContent("fonts/custom.ttf");
注意事项
  • 路径相对于 rawfile 目录
  • 不需要写 rawfile 前缀
  • 区分大小写
  • 使用正斜杠/分隔路径

六、实际开发中的最佳实践

1. 文件分类管理

建议在 rawfile 下创建子目录进行分类:

  • rawfile/config/ - 配置文件
  • rawfile/data/ - 数据文件
  • rawfile/fonts/ - 字体文件
  • rawfile/docs/ - 文档文件
2. 异步读取

文件读取是 IO 操作,建议使用异步方式,避免阻塞 UI 线程。可以将读取操作放在 Promise 或 async 函数中。

3. 错误处理

读取文件可能失败,需要添加 try-catch 错误处理,避免应用崩溃。

4. 缓存机制

频繁读取的文件可以缓存到内存中,避免重复读取提升性能。

5. 文件大小控制

rawfile 中的文件会打包到应用中,文件太大会增加应用体积。大文件建议放在服务器,应用启动后下载。

七、字节数组转换技巧

转换为字符串

读取到的 Uint8Array 需要转换才能使用:

  • 使用 TextDecoder 将字节数组转为字符串
  • 指定编码格式(通常是’utf-8’)
转换为 JSON 对象
  • 先将字节数组转为字符串
  • 再使用 JSON.parse 解析成对象
  • 注意捕获解析异常

八、常见问题

问:rawfile 中的文件可以修改吗?
答:不可以。rawfile 是只读的,打包在应用中,无法在运行时修改。如果需要修改,应该读取后保存到沙箱目录。

问:图片可以放 rawfile 吗?
答:可以,但不推荐。图片应该放 media 目录,系统会自动优化。只有特殊格式或需要保持原始状态的图片才放 rawfile。

问:rawfile 文件太大影响应用吗?
答:会。rawfile 中的所有文件都会打包到应用中,增加应用体积。大文件建议使用网络下载。

问:可以在 rawfile 中创建数据库文件吗?
答:可以放初始的数据库文件,但运行时需要复制到沙箱目录才能读写操作。

问:路径写错会怎样?
答:getRawFileContent 会抛出异常,需要 try-catch 捕获,否则应用会崩溃。

九、性能优化建议

1. 按需加载

不要在应用启动时读取所有 rawfile 文件,按需读取减少启动时间。

2. 合理拆分

如果有大量配置数据,不要放在一个大文件中,拆分成多个小文件,按需加载。

3. 使用缓存

读取后缓存到内存,避免重复读取 IO 操作。

4. 异步加载

使用异步方式读取,不阻塞主线程,保持 UI 流畅。

十、与网络请求的对比

何时用 rawfile
  • 应用内置的固定配置
  • 离线场景必需的数据
  • 首次启动的默认数据
  • 不需要频繁更新的数据
何时用网络请求
  • 需要实时更新的数据
  • 数据量大的内容
  • 个性化或动态数据
  • 需要根据用户定制的内容
混合方案

实际开发中常用的方案:rawfile 提供默认数据,启动后从网络获取最新数据更新。这样既保证离线可用,又能保持数据新鲜。

总结

在 rawfile 目录创建文件后,通过 ResourceManager 的 getRawFileContent 方法读取,传入文件相对路径即可。读取到的是 Uint8Array 字节数组,需要转换为字符串或 JSON 对象使用。rawfile 适合存放配置文件、文本文档、字体等原始资源,注意文件是只读的且会增加应用体积,大文件应考虑网络下载方案。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐