什麼是檔案魔數(Magic Number)?格式辨識原理與常見範例
發佈於 2026 年 4 月 24 日 · 閱讀約 6 分鐘
作業系統怎麼知道檔案類型?
把一個 PNG 檔案改名成 .txt,用 macOS 的 Quick Look 預覽,它依然能正確顯示圖片。在 Linux 上執行 file renamed.txt,輸出依然是 PNG image data。檔名明明改了,為什麼格式沒變?
因為作業系統辨識格式從來不靠檔名,而是讀取檔案開頭的幾個固定位元組——這就是魔數(Magic Number),也叫檔案簽章(File Signature)。
這套機制是現代作業系統與瀏覽器的共同基礎。
魔數是什麼?
每種檔案格式在設計時,都會在檔案開頭預留幾個固定位元組作為格式宣告——這就是魔數(Magic Number),也叫檔案簽章(File Signature)或檔頭(File Header)。
類比一下:你出入境時,海關不需要聽你自我介紹,直接翻開護照第一頁就能確認國籍。魔數就是檔案的「護照首頁」——不管檔案叫什麼名字,打開頭幾個位元組就能確認真實身分。
這也是 Unix file 指令的運作原理:它維護了一份 magic 規則庫,透過位元組比對而不是副檔名來判斷格式。Windows 檔案總管、macOS Finder、瀏覽器 MIME 嗅探——底層邏輯都一樣。檔案類型由內容決定,不由名稱決定。
常見格式魔數速查表
以下是開發中最常見格式的檔頭簽章,均來自實際位元組定義:
| 格式 | 魔數(Hex) | 可讀形式 | 備註 |
|---|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | ‰PNG.... | 8 位元組,最易辨認的簽章之一 |
| JPEG | FF D8 FF | — | 3 位元組,第 3 位元組因子類型略有差異 |
| GIF | 47 49 46 38 | GIF8 | 後接 37(GIF87a)或 39(GIF89a) |
| 25 50 44 46 | %PDF | 後接版本號,如 -1.7 | |
| WebP | 52 49 46 46 … 57 45 42 50 | RIFF…WEBP | RIFF 容器,需看偏移 8–11 位元組 |
| WAV | 52 49 46 46 … 57 41 56 45 | RIFF…WAVE | RIFF 容器,子類型為 WAVE |
| MP3 | 49 44 33 / FF Fx | ID3 / sync | 有 ID3 標籤看前 3 位元組;無標籤時第 2 位元組高 3 位元為 111 |
| FLAC | 66 4C 61 43 | fLaC | 無損音訊,簽章清晰 |
| MP4 / MOV / M4A | 00 00 00 xx 66 74 79 70 | ....ftyp | ftyp 容器,需看偏移 8–11 的品牌標識(major brand) |
| WebM | 1A 45 DF A3 | — | EBML 容器標頭 |
| OGG | 4F 67 67 53 | OggS | 音訊/視訊 OGG 容器 |
| BMP | 42 4D | BM | Windows 點陣圖 |
陷阱:只看前 4 位元組會誤判
表格裡有兩類格式需要特別注意——RIFF 容器和 ftyp 容器。它們的前幾個位元組相同,但實際上包含完全不同的媒體類型,只看前 4 位元組會直接誤判。
RIFF 容器(WebP / WAV / AVI)
WebP、WAV、AVI 都以 RIFF(52 49 46 46)開頭。真正的子類型藏在偏移 8–11 位元組處:
ftyp 容器(MP4 / MOV / M4A)
MP4、MOV、M4A 的開頭 4 位元組是可變的 box 大小,偏移 4–7 位元組固定為 ftyp,偏移 8–11 位元組才是品牌碼,決定具體格式:
常見品牌碼:isom / iso2 / avc1 = MP4,M4A = M4A(Apple 音訊),qt = QuickTime MOV。
動手驗證:用 file 指令讀取魔數
在 macOS 和 Linux 上,file 指令透過讀取檔案原始位元組並與 magic 規則庫比對來辨識格式,與副檔名無關:
# macOS / Linux
$ file -b photo.png
PNG image data, 617 x 875, 8-bit/color RGBA, non-interlaced
$ file -b photo.txt # 將副檔名改為 .txt
PNG image data, 617 x 875, 8-bit/color RGBA, non-interlaced file 是 macOS 和 Linux 的內建工具,Windows 沒有原生等效指令。
如果需要在程式碼中實作相同的格式偵測邏輯,核心只需要這幾行 JavaScript:
// 取 Base64 字串前 24 個字元(atob 解碼後 = 18 位元組),用於格式偵測
// (每 4 個 Base64 字元 = 3 位元組)
const b64 = "iVBORw0KGgoAAAANSUhEUgAA...";
const bin = atob(b64.slice(0, 24));
const hex = [...bin]
.map(c => c.charCodeAt(0).toString(16).padStart(2, "0"))
.join(" ");
console.log(hex);
// → 89 50 4e 47 0d 0a 1a 0a ...(PNG) 對照速查表:89 50 4e 47 是 PNG,ff d8 ff 是 JPEG,25 50 44 46 是 PDF。
小結
檔案類型由二進位標頭的魔數決定,與檔名和副檔名無關。只要讀取開頭幾個位元組並與已知簽章對比,就能在沒有任何上下文的情況下準確辨識格式。
這也是為什麼改副檔名騙不過作業系統——也騙不過任何讀魔數的工具。
相關文章
優雅地除錯 JSON API 回應中的 Base64 圖片 →ViewJSON 在渲染 JSON 時會自動對字串值做魔數偵測,Base64 圖片、音訊和視訊直接內嵌預覽。
立即體驗
把包含 Base64 內容的 JSON 貼進來,ViewJSON 會自動偵測格式,支援圖片、音訊和視訊一鍵預覽。
開啟 ViewJSON →