部落格

什麼是檔案魔數(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)
PDF 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 都以 RIFF52 49 46 46)開頭。真正的子類型藏在偏移 8–11 位元組處:

+0
RIFF
固定前綴
+4
檔案大小 (4 位元組)
+8
子類型 WEBP / WAVE / AVI
決定真實格式
+12
chunk 資料

ftyp 容器(MP4 / MOV / M4A)

MP4、MOV、M4A 的開頭 4 位元組是可變的 box 大小,偏移 4–7 位元組固定為 ftyp偏移 8–11 位元組才是品牌碼,決定具體格式:

+0
box 大小 (可變)
+4
ftyp
固定標識
+8
品牌標識 isom / M4A / qt
決定真實格式
+12
相容列表

常見品牌碼: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 →