HarmonyOS 5.0.0 或以上:文件与数据库混合存储策略(大字段写文件 + 元数据入 SQLite)

HarmonyOS 5.0.0 或以上:文件与数据库混合存储策略(大字段写文件 + 元数据入 SQLite)


📌 场景介绍

对于以下情况,不建议将大内容直接存入 SQLite:

  • 大体积字段:图片、音频、Base64 文件

  • 高频读写场景(避免数据库膨胀)

  • 文件下载缓存、语音留言、本地日志

推荐方案:

内容写入文件系统,元信息写入数据库
如:路径、时间戳、标签、文件名、类型等


🧱 页面结构

/entry/src/main/ets
  └── pages/
       └── MixedStorageDemo.ets     // 文件+数据库混合存储页面

🧩 MixedStorageDemo.ets 示例页面

import fs from '@ohos.file.fs'
import relationalStore from '@ohos.data.relationalStore'

@Entry
@Component
struct MixedStorageDemo {
  @State logs: Array<{ id: number, file: string, title: string }> = []
  private db: relationalStore.RdbStore | undefined
  private dir: string = '/data/storage/el2/base/files/logs'
  private fileIndex: number = 0

  aboutToAppear() {
    this.init()
  }

  private async init() {
    // 创建目录
    if (!await fs.access(this.dir)) {
      await fs.mkdir(this.dir)
    }

    // 初始化数据库
    const context = getContext(this)
    this.db = await relationalStore.getRdbStore(context, {
      name: 'logmeta.db',
      securityLevel: relationalStore.SecurityLevel.S1
    }, 1, {
      onCreate: async (rdb) => {
        await rdb.executeSql(`CREATE TABLE IF NOT EXISTS log_meta (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          title TEXT,
          file TEXT
        )`)
      }
    })

    this.queryLogs()
  }

  private async writeLogAndInsertMeta() {
    const content = `本地日志内容-${new Date().toLocaleString()}`
    const filePath = `${this.dir}/log_${this.fileIndex++}.txt`

    const file = await fs.open(filePath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY | fs.OpenMode.TRUNC)
    await fs.write(file.fd, new TextEncoder().encode(content))
    await fs.close(file.fd)

    await this.db?.insert('log_meta', { title: `日志 ${this.fileIndex}`, file: filePath })
    this.queryLogs()
  }

  private async queryLogs() {
    const resultSet = await this.db?.querySql('SELECT * FROM log_meta ORDER BY id DESC')
    const list: Array<{ id: number, file: string, title: string }> = []

    while (resultSet?.goToNextRow()) {
      list.push({
        id: resultSet.getInteger(0),
        title: resultSet.getString(1),
        file: resultSet.getString(2)
      })
    }
    resultSet?.close()
    this.logs = list
  }

  private async readFileContent(path: string): Promise<string> {
    try {
      const stat = await fs.stat(path)
      const file = await fs.open(path, fs.OpenMode.READ_ONLY)
      const buf = new Uint8Array(stat.size)
      await fs.read(file.fd, buf)
      await fs.close(file.fd)
      return new TextDecoder().decode(buf)
    } catch {
      return '[文件读取失败]'
    }
  }

  build() {
    Column() {
      Text("🧬 混合存储策略:文件+数据库").fontSize(22).margin(20)

      Button("写入一条日志").onClick(() => this.writeLogAndInsertMeta()).margin(10)

      ForEach(this.logs, (log) => {
        Column()
          .width('100%')
          .padding(10)
          .margin({ top: 10 })
          .backgroundColor('#f7f7f7')
          .borderRadius(6) {
          Text(`📝 ${log.title}`).fontSize(16).fontWeight(FontWeight.Medium)
          Text(`📂 ${log.file}`).fontSize(12).fontColor('#888')
          Button("查看内容").onClick(async () => {
            const content = await this.readFileContent(log.file)
            this.logs = this.logs.map(l => l.id === log.id ? { ...l, content } : l)
          }).fontSize(14).margin({ top: 6 })
          If(log.content, () => {
            Text(log.content!).fontSize(14).fontColor('#333').margin({ top: 6 })
          })
        }
      })
    }
    .padding(20)
    .height('100%')
    .scrollable(true)
  }
}

✅ 效果说明

  • 每次点击按钮生成一条日志:内容写文件,元信息写数据库

  • 文件名、路径、标题存入 SQLite

  • 点击“查看内容”实时从文件读取原文展示


🔧 拓展建议

  • 日志支持分级(debug/info/warn/error)写入

  • 图片、视频等大文件走此策略存储路径即可

  • 批量删除操作同时删除数据库与文件

  • 可封装通用 ContentManager 管理大字段逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值