HarmonyOS应用开发实战:猫猫大作战-沙箱路径的获取和使用
前言HarmonyOS 应用运行在沙箱环境中每个应用有自己独立的私有文件目录不能直接访问系统文件或其他应用的文件。沙箱机制保证了数据隔离性和安全性但也要求开发者正确理解filesDir、cacheDir、tempDir等不同目录的用途。在「猫猫大作战」中玩家战绩需要持久化保存filesDir排行榜缓存数据可以放在cacheDir截图等临时文件用tempDir——选错目录可能导致数据丢失或合规问题。本文以「猫猫大作战」的数据存储路径选择为锚点讲解沙箱路径的完整获取方式和各目录的最佳用途。提示本系列不讲 ArkTS 基础语法与环境搭建假设你已跟完第 1–141 篇。本篇是阶段四第 142 篇。一、沙箱路径的获取1.1 基础获取方式import { common } from kit.AbilityKit; const context getContext() as common.UIAbilityContext; // 持久化数据目录卸载时清除备份随应用 const filesDir context.filesDir; // 输出示例/data/app/el2/100/base/com.maomaodazuozhan.game/files/ // 系统缓存目录系统可自动清理 const cacheDir context.cacheDir; // 输出示例/data/app/el2/100/base/com.maomaodazuozhan.game/cache/ // 临时文件目录系统随时可清理 const tempDir context.tempDir; // 输出示例/data/app/el2/100/base/com.maomaodazuozhan.game/temp/1.2 三个目录的详细对比目录获取方式清理策略备份行为容量限制推荐用途filesDircontext.filesDir卸载时删除随应用备份无严格限制战绩、配置、用户设置cacheDircontext.cacheDir系统可自动清理不备份通常 ≤ 100MB图片缓存、网络请求缓存tempDircontext.tempDir系统随时清理不备份建议 ≤ 10MB临时下载、截图中间文件提示filesDir存储玩家不想丢失的数据如高分记录、游戏进度。cacheDir存储可重新获取的数据如头像缓存、排行榜快照。tempDir存储用完即弃的中间文件如下载中的片段。二、在游戏中的实际应用2.1 保存高分记录filesDirimport { fileIo } from kit.CoreFileKit; import { common } from kit.AbilityKit; async function saveHighScore(score: number): Promisevoid { const context getContext() as common.UIAbilityContext; const filePath ${context.filesDir}/high_score.txt; try { const file fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY); fileIo.writeSync(file.fd, ${score}); fileIo.closeSync(file); console.info(高分已保存: ${score}); } catch (err) { console.error(保存高分失败: ${err.message}); } } async function loadHighScore(): Promisenumber { const context getContext() as common.UIAbilityContext; const filePath ${context.filesDir}/high_score.txt; try { const file fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY); const buf new ArrayBuffer(32); fileIo.readSync(file.fd, buf); fileIo.closeSync(file); return Number(new TextDecoder().decode(buf)); } catch { return 0; // 无记录 } }2.2 缓存排行榜cacheDirasync function cacheLeaderboard(data: string): Promisevoid { const context getContext() as common.UIAbilityContext; const cachePath ${context.cacheDir}/leaderboard.json; const file fileIo.openSync(cachePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC); fileIo.writeSync(file.fd, data); fileIo.closeSync(file); } async function readCachedLeaderboard(): Promisestring | null { const context getContext() as common.UIAbilityContext; const cachePath ${context.cacheDir}/leaderboard.json; try { const file fileIo.openSync(cachePath, fileIo.OpenMode.READ_ONLY); const stat fileIo.statSync(cachePath); const buf new ArrayBuffer(stat.size); fileIo.readSync(file.fd, buf); fileIo.closeSync(file); return new TextDecoder().decode(buf); } catch { return null; // 缓存不存在或已清理 } }三、沙箱路径的安全特性3.1 隔离性// 错误尝试访问其他应用的沙箱 const otherAppPath /data/app/el2/100/base/com.other.game/files/data.txt; fileIo.openSync(otherAppPath, fileIo.OpenMode.READ_ONLY); // ❌ 报错Permission denied // ✅ 正确只在自己的沙箱内操作 const myPath ${context.filesDir}/data.txt; fileIo.openSync(myPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_ONLY);3.2 路径拼接// ✅ 推荐使用完整路径拼接 const configPath ${context.filesDir}/config/game_settings.json; // ✅ 更安全使用 fileIo 的路径 API const dir fileIo.mkdirSync(${context.filesDir}/config, true); // true 递归创建 const filePath ${dir}/game_settings.json;四、文件操作模式详解// fileIo.OpenMode 的常用模式组合 const MODES { // 只读 READ: fileIo.OpenMode.READ_ONLY, // 写入覆盖 WRITE: fileIo.OpenMode.WRITE_ONLY, // 读写 READ_WRITE: fileIo.OpenMode.READ_WRITE, // 不存在则创建 CREATE: fileIo.OpenMode.CREATE, // 追加不覆盖 APPEND: fileIo.OpenMode.APPEND, // 清空再写 TRUNC: fileIo.OpenMode.TRUNC, }; // 组合使用 const OPEN_CREATE fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY; const OPEN_READ fileIo.OpenMode.READ_ONLY;模式组合文件不存在文件已存在使用场景READ_ONLY报错正常读取读取已有配置CREATE | WRITE_ONLY创建新文件打开写入不清空追加日志CREATE | WRITE_ONLY | TRUNC创建新文件清空后写入覆盖保存READ_WRITE报错正常读写修改配置提示TRUNC标志清空文件内容——慎用会丢失已有数据。使用APPEND保留已有内容在末尾追加。五、缓存管理策略5.1 缓存有效期async function isCacheValid(cachePath: string, maxAgeMs: number): Promiseboolean { try { const stat fileIo.statSync(cachePath); const now Date.now(); const age now - stat.mtime; // 文件最后修改时间 return age maxAgeMs; } catch { return false; // 文件不存在视为过期 } } // 使用排行榜缓存 1 小时有效 const CACHE_MAX_AGE 60 * 60 * 1000; // 1 小时 const cachePath ${context.cacheDir}/leaderboard.json; if (await isCacheValid(cachePath, CACHE_MAX_AGE)) { const data await readCachedLeaderboard(); // 使用缓存数据 } else { const data await fetchLeaderboardFromServer(); await cacheLeaderboard(data); // 使用新数据 }5.2 缓存清理// 游戏启动时清理过期缓存 async function cleanExpiredCache(context: common.UIAbilityContext): Promisevoid { const cacheDir context.cacheDir; const files fileIo.listFileSync(cacheDir); const MAX_CACHE_AGE 7 * 24 * 60 * 60 * 1000; // 7 天 for (const file of files) { const filePath ${cacheDir}/${file}; try { const stat fileIo.statSync(filePath); if (Date.now() - stat.mtime MAX_CACHE_AGE) { fileIo.unlinkSync(filePath); console.info(已清理过期缓存: ${file}); } } catch (err) { console.error(清理缓存失败: ${err.message}); } } }六、目录操作6.1 递归创建目录function ensureDirExists(dirPath: string): void { try { fileIo.mkdirSync(dirPath, true); // true 递归创建父目录 } catch (err) { if (err.code ! 13900015) { // EEXIST目录已存在 throw err; } } } // 使用 const backupDir ${context.filesDir}/backups/2026/07; ensureDirExists(backupDir); // 目录不存在时自动创建backups/ → backups/2026/ → backups/2026/076.2 目录列表function listSavedGames(context: common.UIAbilityContext): string[] { const saveDir ${context.filesDir}/saves; try { const files fileIo.listFileSync(saveDir); return files.filter(f f.endsWith(.json)); } catch { return []; // saves 目录尚不存在 } }七、沙箱路径与 RDB 数据库的配合7.1 数据库位置import { relationalStore } from kit.ArkData; async function getDatabase(context: common.UIAbilityContext): PromiserelationalStore.RdbStore { const config { name: cat_game.db, // 数据库文件默认在 filesDir securityLevel: relationalStore.SecurityLevel.S1, }; // 数据库文件实际路径{filesDir}/rdb/cat_game.db const store await relationalStore.getRdbStore(context, config); return store; }7.2 数据库导出与备份async function backupDatabase(context: common.UIAbilityContext): Promisestring { const dbPath ${context.filesDir}/rdb/cat_game.db; const backupDir ${context.filesDir}/backups; ensureDirExists(backupDir); const timestamp new Date().toISOString().replace(/[:.]/g, -); const backupPath ${backupDir}/cat_game_${timestamp}.db; fileIo.copyFileSync(dbPath, backupPath); console.info(数据库已备份到: ${backupPath}); return backupPath; }八、沙箱路径与文件选择器8.1 通过 DocumentPicker 导出文件import { picker } from kit.CoreFileKit; async function exportToUserDir(context: common.UIAbilityContext, srcPath: string): Promisevoid { const documentPicker new picker.DocumentViewPicker(context); const uri await documentPicker.save({ fileType: application/json, defaultFileName: game_data_export.json, }); if (uri.length 0) { fileIo.copyFileSync(srcPath, uri[0]); console.info(文件已导出: ${uri[0]}); } }九、调试沙箱路径// 在 DevEco Studio 中使用 hdc 查看沙箱文件 // hdc shell // cd /data/app/el2/100/base/com.maomaodazhuozhan.game/files/ // ls -la // 代码内打印路径 function debugSandboxPaths(context: common.UIAbilityContext): void { console.info([Sandbox] filesDir: ${context.filesDir}); console.info([Sandbox] cacheDir: ${context.cacheDir}); console.info([Sandbox] tempDir: ${context.tempDir}); console.info([Sandbox] databaseDir: ${context.databaseDir}); console.info([Sandbox] preferencesDir: ${context.preferencesDir}); console.info([Sandbox] bundleCodeDir: ${context.bundleCodeDir}); }调试方式命令/工具用途hdc shellcd {filesDir} ls -la查看沙箱文件hdc file recvhdc file recv {remote} {local}拉取沙箱文件到电脑hdc file sendhdc file send {local} {remote}推送文件到沙箱DevEco StudioDevice File Explorer可视化浏览沙箱文件十、安全检查清单敏感数据放在filesDir而非cacheDir缓存数据设置有效期定期清理临时文件用完删除不使用硬编码的绝对路径不同设备路径不同文件操作捕获异常处理文件不存在的场景数据库文件默认在 filesDir无需手动设置路径跨应用数据共享使用 FilePicker 或 DataShare十一、版本差异API 版本沙箱路径变化影响API 9 及以下路径包含com.xxx.xxx基础沙箱API 10bundleName 替代包名路径格式调整API 11应用克隆路径隔离多用户隔离API 12加密沙箱支持数据加密存储总结HarmonyOS 沙箱路径通过context.filesDir持久、context.cacheDir缓存、context.tempDir临时三个核心入口管理应用私有文件。核心要点filesDir存玩家数据不丢失、cacheDir存可重新获取的数据、tempDir用完即弃、 文件操作捕获EEXIST/ENOENT等异常、 绝对路径因设备和版本而异、 沙箱隔离保证数据安全。下一篇将深入 JSON 序列化——stringify 与 parse 在游戏数据持久化中的应用。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源Context 上下文 API 文档沙箱路径官方指南fileIo 文件操作 API关系型数据库 RDBDocumentPicker 文件选择器HarmonyOS 数据存储概述开源鸿蒙跨平台社区HarmonyOS 开发者官方文档第 141 篇fileIo 文件操作第 143 篇JSON 序列化

相关新闻

如何快速制作集成最新补丁的Windows安装镜像:终极自动化方案

如何快速制作集成最新补丁的Windows安装镜像:终极自动化方案

如何快速制作集成最新补丁的Windows安装镜像:终极自动化方案 【免费下载链接】Win_ISO_Patching_Scripts Win_ISO_Patching_Scripts 项目地址: https://gitcode.com/gh_mirrors/wi/Win_ISO_Patching_Scripts 想要为Windows系统部署准备一个包含所有最新安全补…

2026/10/27 1:17:45 阅读更多 →
零样本语音克隆技术:1分钟实现高拟真声音合成

零样本语音克隆技术:1分钟实现高拟真声音合成

1. 项目概述:一分钟实现零样本声音克隆的技术突破 这个开源项目实现了一个惊人的能力——只需1分钟音频样本,就能训练出高度拟真的个性化语音合成模型。作为从业多年的语音技术开发者,我亲测其效果已经达到商用级水平。传统TTS系统需要数小时…

2026/10/27 2:05:16 阅读更多 →
AIGC论文检测与降重策略:2026学术规范应对指南

AIGC论文检测与降重策略:2026学术规范应对指南

1. 博士论文AIGC痕迹检测现状与挑战 2026年的学术环境对论文原创性提出了前所未有的严格要求。全球主要学术机构已普遍采用第四代AI检测系统,其核心算法结合了语义指纹分析、写作风格识别和内容溯源技术。以Turnitin的GenAI Detector 4.0为例,系统不仅能…

2026/10/23 21:42:11 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/25 22:36:10 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/26 5:00:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/26 3:16:46 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 12:00:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →