本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
在鸿蒙(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();
五、优化与建议
- 路径处理工具封装
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-8 | 用TextDecoder指定编码 |
| 权限拒绝 | 未申请存储权限 | 配置requestPermissions |
| 内存溢出 | 文件过大 | 改用分块读取或流式解析 |
774






