鸿蒙开发中,读取本地JSON文件

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

在鸿蒙(HarmonyOS)开发中,读取本地JSON文件主要通过 文件管理API资源访问API 实现。以下是代码示例:

一、两种核心读取方式对比

方式适用场景路径类型是否需要权限
RawFile资源访问打包在应用内的静态JSON文件$rawfile() 或 Resource❌ 否
沙箱文件访问运行时动态写入/下载的JSON/data/storage/...✅ 是

二、读取打包的JSON文件(无需权限)

1. 通过$rawfile读取(推荐)
import util from '@ohos.util';

@Entry
@Component
struct JsonDemo {
  @State data: object = {};

  aboutToAppear() {
    // 1. 读取rawfile下的json文件
    let jsonStr = getContext(this).resourceManager.getRawFileContentSync('data.json');
    
    // 2. 解析JSON
    try {
      this.data = JSON.parse(jsonStr);
      console.log('解析结果:', this.data);
    } catch (err) {
      console.error('JSON解析失败:', err);
    }
  }

  build() {
    Column() {
      Text(JSON.stringify(this.data))
    }
  }
}

文件位置:resources/rawfile/data.json,HarmonyOS的打包工具会将该目录文件内容预编译为UTF-8字符串格式,无需手动解码。

2. 通过Resource对象读取
let resource = getContext(this).resourceManager;
resource.getRawFileContent('data.json').then(jsonStr => {
  this.data = JSON.parse(jsonStr);
});

三、读取沙箱内的JSON文件(需权限)

1. 文件路径说明
目录类型路径示例访问方式
应用私有目录/data/storage/el2/base/files/直接读写
公共媒体目录/media/JSON/需申请存储权限
2. 完整读取流程
import fs from '@ohos.file.fs';
import { BusinessError } from '@ohos.base';

async function readSandboxJson(fileName: string): Promise<object> {
  // 1. 获取沙箱文件路径
  const context = getContext(this) as common.UIAbilityContext;
  const filePath = `${context.filesDir}/${fileName}`;
  
  // 2. 检查文件是否存在
  try {
    if (!fs.accessSync(filePath)) {
      throw new Error('文件不存在');
    }
    
    // 3. 打开并读取文件
    let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
    let stat = fs.statSync(filePath);
    let buffer = new ArrayBuffer(stat.size);
    fs.readSync(file, buffer);
    
    // 4. 转换为JSON对象
    let decoder = util.TextDecoder.create('utf-8');
    let jsonStr = decoder.decode(buffer);
    return JSON.parse(jsonStr);
    
  } catch (err) {
    const error = err as BusinessError;
    console.error(`[${error.code}] 读取失败: ${error.message}`);
    throw error;
  } finally {
    if (file) fs.closeSync(file);
  }
}

// 调用示例
readSandboxJson('config.json').then(data => {
  console.log('配置数据:', data);
});

当读取沙箱内的文件时,fs.readSync()返回的是原始的ArrayBuffer二进制数据,系统无法自动判断文件是UTF-8、GBK还是其他编码,必须手动解码。 

权限配置(仅公共目录需要):

// module.json5
"requestPermissions": [
  {
    "name": "ohos.permission.READ_MEDIA",
    "reason": "读取公共JSON文件"
  }
]

四、特殊场景处理

1. 大文件分块读取
async function readLargeJson(filePath: string): Promise<object> {
  const CHUNK_SIZE = 1024 * 1024; // 1MB分块
  let fullText = '';
  
  let fd = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
  let stat = fs.statSync(filePath);
  
  for (let offset = 0; offset < stat.size; offset += CHUNK_SIZE) {
    let chunkSize = Math.min(CHUNK_SIZE, stat.size - offset);
    let buffer = new ArrayBuffer(chunkSize);
    fs.readSync(fd, buffer, { offset });
    fullText += new util.TextDecoder().decode(buffer);
  }
  
  fs.closeSync(fd);
  return JSON.parse(fullText);
}

2. 监听文件变化

import fileIO from '@ohos.fileio';

function watchJsonFile(filePath: string, callback: (data: object) => void) {
  let watcher = fileIO.createWatcher(filePath, 500); // 500ms轮询
  
  watcher.on('change', () => {
    let newData = readSandboxJson(filePath);
    callback(newData);
  });
  
  return watcher;
}

// 使用示例
const watcher = watchJsonFile('dynamic.json', data => {
  console.log('文件已更新:', data);
});

// 停止监听
watcher.stop();

五、优化与建议

  1. 路径处理工具封装
class PathHelper {
  static getSandboxPath(fileName: string): string {
    const context = getContext(this) as common.UIAbilityContext;
    return `${context.filesDir}/${fileName}`;
  }

  static getRawFilePath(fileName: string): string {
    return `$rawfile/${fileName}`;
  }
}

    2. JSON解析安全校验 

function safeParse(jsonStr: string): object | null {
  try {
    return JSON.parse(jsonStr);
  } catch {
    return null;
  }
}

  3. 性能优化

  • 频繁读取的JSON文件可做内存缓存
  • 大文件优先使用流式解析(如JSON.parse()分块)

六、常见问题

问题原因修复方案
文件找不到路径错误或未打包检查文件是否在resources/rawfile/
JSON解析失败文件编码非UTF-8TextDecoder指定编码
权限拒绝未申请存储权限配置requestPermissions
内存溢出文件过大改用分块读取或流式解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值