7-Zip 檔案格式
7-Zip 壓縮檔,通常透過 LZMA/LZMA2 達到很高的壓縮率。
- MIME 類型
- application/x-7z-compressed
- 副檔名
- .7z
- 分類
- 壓縮與封存
Magic number(檔案簽章)
| 0x00000000 | 377ABCAF271C | 7z··'· | 7z magic |
關於 7-Zip 格式
7z 是 7-Zip 的原生格式,支援強力的 LZMA2 壓縮、solid 封存與 AES-256 加密。簽章是 37 7A BC AF 27 1C。前三十二個位元組就是整份固定排版的全部:一個簽章、一個格式版本,加上一個指向真正標頭所在位置的指標。其他所有東西 — 檔名、大小、時間戳、檢查碼,以及資料是怎麼編碼的描述 — 全都坐在檔案另一端的那份標頭裡,而且通常它自己也是壓縮過的。中間沒有任何逐檔標頭,這就是 .7z 精簡的原因,也是為什麼一個受損的 .7z 比 ZIP 難搶救得多。
檔頭結構,一個位元組一個位元組看
| 位移 | 長度 | 欄位 | 意義 |
|---|---|---|---|
| 0 | 6 | Signature | 37 7A BC AF 27 1C。前兩個位元組是 ASCII 的 '7z' 兩個字母,所以它們會以看得懂的文字出現;後面四個是刻意挑的任意二進位值,好讓任何文字檔都不可能撞上。 |
| 6 | 1 | Format major version | 至今寫出來的每個封存檔都是 0。這裡要是改了,就代表結構不相容的新格式,所以讀取端把其他值當成拒收的理由,而不是一個警告。 |
| 7 | 1 | Format minor version | 現在的封存檔是 4。次版本是向後相容的增補,所以看得懂 0.4 的讀取端,比它舊的全部應付得來。 |
| 8 | 4 | Start header CRC-32 | 小端序,剛好涵蓋位移 12 到 31 那二十個位元組。它保護的是其他一切所依賴的那個指標,所以讀取端在 seek 到任何地方之前,就能分得出是前綴壞了還是本體壞了。 |
| 12 | 8 | Next header offset | 一個小端序 64 位元位移,指向真正的標頭 — 從位移 32、也就是這份簽章標頭的結尾算起,不是從檔案開頭算起。在一個 200246 位元組的封存檔裡它讀到 F4 0D 03 00 00 00 00 00,也就是 200180,所以標頭從 200212 開始。 |
| 20 | 8 | Next header size | 那份標頭的長度,小端序 64 位元。它和位移合起來必須剛好落在檔案結尾:32 加 200180 加 34 是 200246,正是檔案的實際大小 — 這道算術是現成最快的完整性檢查。 |
| 28 | 4 | Next header CRC-32 | 前兩個欄位所指向的那份標頭的檢查碼,小端序,所以那裡的損壞在任何剖析嘗試之前就會被偵測到。 |
| 32 | variable | Packed streams | 壓縮資料本身,緊接在三十二個位元組的簽章標頭之後寫入。在 solid 封存檔裡,這是一條橫跨很多檔案的連續編碼串流,而不是一個檔案一條串流。 |
| variable | variable | Header | 位置是 32 加上 next header offset:這是封存檔真正的目錄 — 名稱、大小、CRC、時間戳、屬性,以及描述怎麼把壓縮串流解出來的編碼器鏈。它通常自己也是 LZMA 壓縮過的,而開啟標頭加密時,它還會被加密。 |
怎麼跟長得像的格式分開
| 容易搞混的 | 怎麼分 |
|---|---|
| XZ | 真正會害人出錯的就是這一個。.xz 開頭是 FD 37 7A 58 5A 00,所以 37 7A 這兩個位元組出現在位移 1,而 ASCII 的 '7zXZ' 在 hex dump 裡清清楚楚。真正的 .7z 是位移 0 就 37 7A BC AF 27 1C。差一格,兩種毫無關係的格式:.7z 是帶目錄的多檔案封存檔,.xz 是單一條壓縮串流。 |
| ZIP | 位元組上沒有任何共通處 — 50 4B 03 04 對上 37 7A BC AF 27 1C — 但兩者是同一個工具寫出來的,標錯名字的情況也一直在發生。結構上的差別在目錄住在哪裡、以及代價多少:ZIP 列出並抽出單一項目很便宜,而一個 solid 的 .7z 為了拿到一個檔案,可能得先解好幾 GB。 |
| RAR5 | 另一個高壓縮率的 Windows 壓縮工具,開頭是 52 61 72 21 1A 07 01 00。它們正面競爭;實務上的差別是 7z 是開放的、可以自由實作,而 RAR 是專有的,另外 RAR 有修復記錄而 7z 沒有。 |
| Self-extracting .exe | 7-Zip 的自解壓縮封存檔是一個後面接著封存檔的 Windows 執行檔,所以位移 0 讀到的是 4D 5A('MZ'),而 37 7A BC AF 27 1C 簽章坐在檔案深處。任何會掃描簽章的 7z 讀取端仍然解得開它,這也是為什麼一個 .exe 可以安全地當成封存檔打開。 |
常見的壞法
- 截斷,而且它比在 ZIP 上痛得多。前三十二個位元組裡的 next header offset 現在指到檔案結尾之外,於是什麼都列不出來 — 而且跟 ZIP 不同,這裡沒有逐檔的區域標頭可以往前掃,因為 .7z 根本就沒有。想部分救援,通常意味著用手把編碼器鏈猜出來。
- 位移 8 的起始標頭 CRC 對不上。前三十二個位元組壞了,而實務上這幾乎一定代表有位元組被加在前面或被剝掉,而不是原地翻了一個位元 — 因為那個區塊很小、又很少被碰到。
- solid 壓縮把局部損壞放大。預設情況下很多檔案被壓成一條連續串流,所以 solid 區塊裡任何位置有一個壞位元組,就會毀掉那個區塊裡在它之後的每一個檔案。關掉 solid 模式建立的封存檔,正是用壓縮率換這種局部收斂。
- 加密的標頭被誤認成損壞。用標頭加密做出來的封存檔,沒有密碼就列不出檔名,所以工具會把它報成讀不了、或什麼都不顯示。這個封存檔完好無缺;它只是拒絕回答。
- 文字模式傳輸。三十二個位元組的簽章標頭活了下來,所以封存檔會被正確辨識、標頭指標也照樣解得到位置,失敗只會在真正解壓縮那些串流時以 CRC 錯誤的形式出現。
這個格式現在還在用嗎
7z 是主流桌面壓縮工具裡的壓縮率冠軍,在 Windows 上,當 ZIP 太大時大家伸手拿的就是它:LZMA2 配上 solid 區塊,在原始碼樹和文件集合上動輒把 ZIP 的產出砍一半,而 AES-256 加密是內建的、不是外掛上去的。這個格式有公開文件,參考實作也免費,所以 libarchive、p7zip 和多數壓縮工具都讀得懂它。它始終沒能成為的是交換格式。它沒有一等公民級的 Unix 權限或符號連結模型,solid 壓縮讓「只抽一個檔案」有可能貴到離譜,而完全沒有逐檔標頭這件事,讓受損的封存檔比受損的 ZIP 難救太多。在 Unix 上同樣的工作是由 tar.xz 或 tar.zst 完成的,權限模型留在 tar 那一層;而任何要交給不特定收件者打開的東西,安全答案仍然是 ZIP。
在這個站上打開 7-Zip 檔
這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。
相關格式
容易和 7-Zip 搞混的格式,可以比對它們的開頭位元組。