各位鸿蒙开发者!今天盘数据存储—— 这可是认证里占 18% 的核心模块,不管是存配置、存列表还是存文件,干活必须会!

一、轻量键值存:Preferences(认证高频考)

存小数据(比如用户偏好、配置项)就用它,步骤保姆级!

步骤 1:初始化 Preferences

// 先导入模块

import dataPreferences from '@ohos.data.preferences';

@Entry

@Component

struct PrefPage {

  // 定义Preferences实例

  private pref: dataPreferences.Preferences | null = null;

  build() {

    Column() {

      Button('初始化Preferences')

        .onClick(async () => {

          // 打开名为"user_config"的Preferences文件(没有会自动创建)

          this.pref = await dataPreferences.getPreferences(getContext(this), 'user_config');

          promptAction.showToast({ message: '初始化完成' });

        })

    }

  }

}

步骤 2:存数据 + 取数据

// 接上面的代码,加存/取按钮

Button('存用户昵称')

  .onClick(async () => {

    if (this.pref) {

      // 存键值对(支持string/number/boolean等)

      await this.pref.put('user_nickname', '鸿蒙小能手');

      await this.pref.flush(); // 必须flush才会真正存到本地!

      promptAction.showToast({ message: '昵称已存' });

    }

  })

Button('取用户昵称')

  .onClick(async () => {

    if (this.pref) {

      // 取数据(第二个参数是默认值)

      const nickname = await this.pref.get('user_nickname', '默认昵称');

      promptAction.showToast({ message: `昵称是:${nickname}` });

    }

  })

⚠️ 认证考点标红

Preferences 的限制要记牢:

  1. 单个文件大小不超过1MB(存小数据专用);
  2. 不支持跨应用访问;
  3. 必须调用flush()才会持久化(否则只存在内存);
  4. 支持的数据类型:string、number、boolean、Array、Object(简单对象)。


二、结构化存:关系型数据库(认证必考)

存列表数据(比如用户列表、订单)用这个,直接上增删改查!

步骤 1:创建数据库 + 表

import relationalStore from '@ohos.data.relationalStore';

@Entry

@Component

struct DbPage {

  private rdbStore: relationalStore.RdbStore | null = null;

  build() {

    Column() {

      Button('创建用户表')

        .onClick(async () => {

          // 配置数据库

          const storeConfig = {

            name: 'user_db.db', // 数据库名

            securityLevel: relationalStore.SecurityLevel.S1 // 安全级别

          };

          // 打开数据库

          this.rdbStore = await relationalStore.getRdbStore(getContext(this), storeConfig);

          // 创建表(user表:id主键、name、age)

          const createTableSql = 'CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)';

          await this.rdbStore.executeSql(createTableSql);

          promptAction.showToast({ message: 'user表创建完成' });

        })

    }

  }

}

步骤 2:增删改查实战

(1)新增数据
Button('新增用户')

  .onClick(async () => {

    if (this.rdbStore) {

      const valuesBucket = { name: '张三', age: 25 };

      // 插入数据到user表

      const insertId = await this.rdbStore.insert('user', valuesBucket);

      promptAction.showToast({ message: `用户新增成功,ID:${insertId}` });

    }

  })
(2)查询数据
Button('查询所有用户')

  .onClick(async () => {

    if (this.rdbStore) {

      // 查询id、name、age字段

      const resultSet = await this.rdbStore.query('user', ['id', 'name', 'age']);

      // 遍历结果集

      while (resultSet.goToNextRow()) {

        const id = resultSet.getLong(0); // 第0列是id(long类型)

        const name = resultSet.getString(1); // 第1列是name(string类型)

        const age = resultSet.getLong(2); // 第2列是age(long类型)

        console.log(`用户信息:id=${id}, name=${name}, age=${age}`);

        promptAction.showToast({ message: `找到用户:${name}` });

      }

      resultSet.close(); // 用完必须关闭,避免内存泄漏!

    }

  })
(3)修改数据
Button('修改张三年龄为26')

  .onClick(async () => {

    if (this.rdbStore) {

      const valuesBucket = { age: 26 };

      // 条件:name = '张三'

      const condition = 'name = ?';

      const bindArgs = ['张三'];

      // 更新数据

      const updateCount = await this.rdbStore.update('user', valuesBucket, condition, bindArgs);

      promptAction.showToast({ message: `修改了${updateCount}条数据` });

    }

  })
(4)删除数据
Button('删除张三')

  .onClick(async () => {

    if (this.rdbStore) {

      const condition = 'name = ?';

      const bindArgs = ['张三'];

      // 删除数据

      const deleteCount = await this.rdbStore.delete('user', condition, bindArgs);

      promptAction.showToast({ message: `删除了${deleteCount}条数据` });

    }

  })

⚠️ 认证考点标红

  1. 数据库安全级别:S1(普通安全)、S2(高安全),默认 S1;
  2. 结果集resultSet必须调用close(),否则会内存泄漏(认证常考);
  3. 支持 SQLite 语法,可直接执行复杂查询(比如WHERE、ORDER BY);
  4. 适合存储结构化、关联型数据(比如订单表和用户表关联)。


三、文件存:存图片 / 音频 / 大文本(认证常考场景)

存大文件(比如头像、下载的文件、长文本)用文件存储,直接操作应用沙箱目录!

步骤 1:存文本文件

import fileio from '@ohos.fileio';

import fs from '@ohos.file.fs';

Button('存文本文件到应用目录')

  .onClick(async () => {

    try {

      // 1. 获取应用的文件存储目录(files目录)

      const context = getContext(this);

      const filesDir = context.filesDir; // 路径格式:/data/storage/el2/base/xxx/files

      

      // 2. 拼接文件路径(文件名:note.txt)

      const filePath = `${filesDir}/note.txt`;

      

      // 3. 写文件(READ_WRITE:读写权限,CREATE:不存在则创建)

      const fd = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);

      

      // 4. 写入内容(支持字符串或Buffer)

      const content = '这是鸿蒙开发的学习笔记,文件存储实战!';

      fileio.writeSync(fd, content);

      

      // 5. 关闭文件描述符(必须关!)

      fs.closeSync(fd);

      

      promptAction.showToast({ message: `文本文件已保存:${filePath}` });

    } catch (err) {

      promptAction.showToast({ message: `保存失败:${err.message}` });

    }

  })

步骤 2:读文本文件

Button('读取文本文件')

  .onClick(async () => {

    try {

      const context = getContext(this);

      const filesDir = context.filesDir;

      const filePath = `${filesDir}/note.txt`;

      

      // 打开文件(只读模式)

      const fd = fs.openSync(filePath, fs.OpenMode.READ_ONLY);

      

      // 读取文件内容(指定读取长度,这里设为1024字节)

      const buffer = new ArrayBuffer(1024);

      const readLen = fileio.readSync(fd, buffer);

      

      // 转换Buffer为字符串

      const content = String.fromCharCode.apply(null, new Uint8Array(buffer.slice(0, readLen)));

      

      // 关闭文件

      fs.closeSync(fd);

      

      promptAction.showToast({ message: `文件内容:${content}` });

    } catch (err) {

      promptAction.showToast({ message: `读取失败:${err.message}` });

    }

  })

步骤 3:存图片文件(比如网络图片下载后存储)

// 先导入网络请求模块

import http from '@ohos.net.http';

Button('下载图片并存储')

  .onClick(async () => {

    try {

      // 1. 发起网络请求下载图片(这里用一张测试图片)

      const httpClient = http.createHttp();

      const response = await httpClient.request('https://picsum.photos/200/200', {

        method: http.RequestMethod.GET

      });

      

      // 2. 获取图片的ArrayBuffer数据

      const imageBuffer = await response.result;

      

      // 3. 存储到应用目录

      const context = getContext(this);

      const filesDir = context.filesDir;

      const imgPath = `${filesDir}/test_img.jpg`;

      

      // 4. 写文件(二进制模式)

      const fd = fs.openSync(imgPath, fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE);

      fileio.writeSync(fd, imageBuffer);

      fs.closeSync(fd);

      

      promptAction.showToast({ message: `图片已保存:${imgPath}` });

    } catch (err) {

      promptAction.showToast({ message: `下载失败:${err.message}` });

    }

  })

⚠️ 认证考点标红

  1. 应用沙箱目录:
    1. filesDir:存储应用私有文件(不会被系统清理);
    2. cacheDir:存储缓存文件(系统可能清理);

2.文件操作必须关闭fd(文件描述符),否则会导致资源泄漏;
3.存大文件(超过 100KB)优先用文件存储,不要用 Preferences;

4.跨应用访问文件需要配置权限(认证会问权限相关考点)。


四、三种存储方式对比(认证必背)

存储方式

适用场景

优点

缺点

认证考点频次

Preferences

小数据、配置项(比如开关、昵称)

操作简单、性能高

单个文件≤1MB、不支持复杂查询

高频

关系型数据库

结构化、关联型数据(列表、订单)

支持 SQL 查询、数据关联、事务

操作稍复杂、适合大数据量

必考

文件存储

大文件(图片、音频、长文本)

无大小限制、支持任意文件格式

不支持结构化查询、需自己管理

常考


五、班级

目前班级正火热招募学员!加入班级:https://developer.huawei.com/consumer/cn/training/classDetail/6b5617ffd9264d6daa2f3d9250204f1e?type=1%3Fha_source%3Dhmosclass&ha_sourceId=89000248 ,跟着系列文章系统学,快速掌握鸿蒙开发核心技能,冲刺 HarmonyOS 应用开发者认证!无论你是零基础入门,还是在职开发者提升,都能在班级中收获成长,抢占鸿蒙生态人才红利~

Logo

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

更多推荐