使用 LZ-String 压缩与导出 JavaScript 游戏存档数据

2次阅读

使用 LZ-String 压缩与导出 JavaScript 游戏存档数据

本文详解如何利用 lz-String 库对 json 格式的游戏存档进行高效压缩、存储与还原,实现轻量级、可复制的导入/导出功能,显著减小 localstorage 占用并支持用户手动分享存档字符串

本文详解如何利用 lz-string 库对 json 格式的游戏存档进行高效压缩、存储与还原,实现轻量级、可复制的导入/导出功能,显著减小 localstorage 占用并支持用户手动分享存档字符串。

在 Web 游戏开发中,提供“导出存档”和“导入存档”功能不仅能提升用户体验,还能增强数据可迁移性与社区互动性(例如玩家间交换通关进度)。但直接 JSON.stringify() 后存入 localStorage 存在明显缺陷:数据体积大、易被人工误读/篡改、不便于粘贴分享。此时,LZ-String 是业界广泛采用的轻量级解决方案——它专为 javaScript 设计,无需依赖服务端,纯前端即可完成高压缩比的无损压缩与解压,且输出为可打印字符(UTF-16 安全),非常适合生成用户友好的存档字符串。

✅ 快速集成 LZ-String

首先,通过 CDN 引入官方库(推荐使用 SRI 完整校验):

<script    src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.js"    integrity="sha512-uKcuHr0POVc2zz1hMVTEiicF9G5SPq2k6l4xVmPeSXm8yH/rrM6ewau/Gn89ykaGrfMyhCBH4Vn/MDcS3Pccqw=="    crossorigin="anonymous"    referrerpolicy="no-referrer"> </script>

⚠️ 注意:LZ-String 的 compress() 输出是 二进制安全字符串(不是 Base64),不可与 btoa() 混用;若需 URL 或邮件兼容格式,请使用 compressToBase64() 和 decompressFromBase64()。

? 实现压缩版存档逻辑

以下为优化后的 saveGame() 与 loadGame() 函数,兼顾健壮性与可读性:

立即学习Java免费学习笔记(深入)”;

function saveGame() {   const game_data = {     stars: Game.stars,     totalStarsEarned: Game.totalStarsEarned,     buildings: buildings,     upgrades: upgrades,     achievements: achievements,     // ✅ 建议添加版本标识,便于未来格式升级兼容     version: 1.3,     timestamp: Date.now()   };    try {     const json = JSON.stringify(game_data);     const compressed = LZString.compress(json); // 输出紧凑 UTF-16 字符串     localStorage.setItem("game_data_lz", compressed);     console.log("✅ 游戏已压缩保存(LZ-String)");   } catch (e) {     console.error("❌ 存档压缩失败:", e);   } }  function loadGame() {   const str = localStorage.getItem("game_data_lz");   if (!str) {     console.warn("⚠️ 未找到本地存档");     return false;   }    try {     const decompressed = LZString.decompress(str);     if (!decompressed) {       throw new Error("解压失败:无效压缩数据");     }     const savedGame = JSON.parse(decompressed);      // ✅ 安全赋值:仅覆盖目标属性,避免污染全局状态     if (savedGame.stars !== undefined) Game.stars = savedGame.stars;     if (savedGame.totalStarsEarned !== undefined) Game.totalStarsEarned = savedGame.totalStarsEarned;     if (Array.isArray(savedGame.buildings)) buildings = savedGame.buildings;     if (Array.isArray(savedGame.upgrades)) upgrades = savedGame.upgrades;     if (Array.isArray(savedGame.achievements)) achievements = savedGame.achievements;      console.log("✅ 存档加载成功,版本:", savedGame.version);     return true;   } catch (e) {     console.error("❌ 存档加载失败:", e);     return false;   } }

? 导出/导入字符串:用户交互层示例

为支持用户复制粘贴,补充两个实用函数:

// 导出为可分享字符串(自动复制到剪贴板) function exportSave() {   const str = localStorage.getItem("game_data_lz");   if (!str) return;   navigator.clipboard.writeText(str)     .then(() => alert("✅ 存档已复制!可粘贴至其他设备导入"))     .catch(err => console.error("? 复制失败:", err)); }  // 从用户输入字符串导入 function importSave(saveString) {   if (!saveString || typeof saveString !== 'string') return false;   try {     const decompressed = LZString.decompress(saveString);     const data = JSON.parse(decompressed);     // 此处调用 loadGame 的核心逻辑,或直接赋值     localStorage.setItem("game_data_lz", saveString);     loadGame();     return true;   } catch (e) {     alert("❌ 导入失败:无效存档格式或版本不兼容");     return false;   } }

? 注意事项与最佳实践

  • 永远校验解压结果:LZString.decompress() 对非法输入返回 NULL,必须判空后再 JSON.parse();
  • 添加 version 字段:当游戏数据结构变更时,可在 loadGame() 中检查 savedGame.version 并执行迁移逻辑;
  • 避免压缩空/极小数据:LZ-String 对短字符串可能膨胀,建议 >100 字符再启用压缩(可加长度判断);
  • 不要替代加密:LZ-String 是压缩,非加密;敏感数据需额外 AES 加密(如使用 CryptoJS);
  • 兼容性提示:LZ-String 支持所有现代浏览器(包括 IE10+),无 polyfill 依赖。

通过以上实现,你的 Web 游戏将具备专业级存档管理能力:单字符串导出、毫秒级压缩、跨设备无缝导入,并为后续扩展(如云同步、版本回滚)奠定坚实基础。

text=ZqhQzanResources