| 字段 | 類型 | 長度 | 說明 |
|---|---|---|---|
| Signature | char[] | 6 字節 | 魔數標識,如 "PAK001" |
| Version | float | 4 字節 | 格式版本 |
| FileTableCount | int | 4 字節 | 包含文件數 |
| CipherAction | byte | 1 字節 | 0=加法,1=減法 |
| CipherValue | byte | 1 字節 | 加密鍵值 |
| UniqueID | char[] | 10 字節 | 文件唯一標識 |
| Reserved | int | 4 字節 | 保留擴展 |
| 字段 | 類型 | 長度 | 說明 |
|---|---|---|---|
| FileName | char[] | 30 字節 | 文件名,不足補空 |
| FileSize | int | 4 字節 | 原始文件大小 |
| Offset | int | 4 字節 | 在 Pak 中偏移量 |
按文件表順序拼接的加密後文件二進制數據。
純數據持有類,提供 size() 靜態方法計算結構體大小,支援序列化/反序列化。
makePakFile(String[] srcPaths, String destPath, PakHeader header):掃描源文件→構建文件表→寫入頭/表/加密數據extractFileFromPak(...):解析頭/表→定位偏移→讀取解密→輸出文件或字節數組showPakFileInfo(...):列表 Pak 內容b ± key),J2ME 端解密極快byte[]getClass().getResourceAsStream("/res/data.pak") 讀取 JAR 內資源Image.createImage(bytes, 0, len) 生成圖片// 文件數據區起始偏移
long dataStart = PakHeader.size() + header.getFileTableCount() * PakFileTable.size();
// 第 i 個文件偏移
offset[i] = dataStart + sum_{j< i} fileSize[j];
// 加密 (J2SE) if (action == ADD) b += key; else b -= key; // 解密 (J2ME/J2SE) if (action == ADD) b -= key; else b += key;
res/*.png 打包為 data.pakdata.pak 放入 J2ME 專案 /res 目錄PakUtil.extractResourceFromPak("/res/data.pak", "hero.png") 獲取字節數組Image.createImage(bytes, 0, bytes.length) 直接渲染| 優點 | 缺點/改進 |
|---|---|
| 極簡依賴,無第三方庫 | 加密強度低,建議升級為 XOR/RC4/AES |
| J2ME 端零臨時文件,內存友好 | 不支援壓縮,可引入 LZ77/Deflate |
| 隨機讀取 O(1) 定位 | 文件名長度固定 30 字節,可改為長度前綴 |
| 支援任意二進制資源 | 無目錄結構,可擴展路徑分隔符 |
Pak 方案以最小代價解決了 J2ME 時代的資源體積、保護、讀取三大痛點。其「預製打包 + 運行時隨機讀取」的架構思想,在現代遊戲引擎的 AssetBundle/Pak 系統中依然延續。