
本文详解如何利用 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 游戏将具备专业级存档管理能力:单字符串导出、毫秒级压缩、跨设备无缝导入,并为后续扩展(如云同步、版本回滚)奠定坚实基础。











