解碼 UTF-8 意味著反轉 RFC 3629 所描述的可變寬度位元組編碼,從一串位元組還原原始 Unicode 文字。每個介於 U+0000 與 U+10FFFF 之間的 Unicode 純量值,恰好對應一個、兩個、三個或四個位元組;ASCII 字元(U+0000 到 U+007F)保留其單一位元組值不變,而像露齒笑表情符號 U+1F600 這類補充字元則展開成四個位元組 F0 9F 98 80。當這些位元組以十六進位、十進位或 8 位元二進位記法呈現時,嚴格解碼器會剖析它們、驗證每一個位元組邊界,並回傳對應文字——若序列畸形,則以明確錯誤大聲失敗。UTF-8 Encoder / Decoder 在你的瀏覽器裡正是做這件事:它接受以空白或逗號分隔的位元組詞元、選用的 0x 前綴,或一段連續的偶數長度十六進位字串,然後要嘛還原精確的 Unicode 字元,要嘛拒絕輸入,而不是悄悄插入許多預設解碼器會送出的 U+FFFD 替換字元。因為此工具在本機執行、絕不上傳任何東西,你可以貼上機密位元組序列並檢查結果,不必伺服器往返。

encoding utf 8 decode
編碼 utf 8 解碼

UTF-8 解碼實際代表什麼

UTF-8 工具的解碼端是編碼的相反:它取一串已經遵守 RFC 3629 規則的位元組序列,並重建那些位元組所代表的 Unicode 純量值。編碼把每個純量對應到特定的一到四位元組模式;解碼則讀取前導位元組以得知後面跟著幾個延續位元組,再把酬載位元縫在一起,還原原始碼位。

UTF-8 區分四種前導位元組範圍。以 0 開頭的位元組直接承載純量,總共使用一個位元組。以 110 開頭的位元組引入兩個位元組的序列,1110 引入三個位元組的序列,11110 引入四個位元組的序列。每個延續位元組必須以位元 10 開頭,重建出的純量值不得超過 U+10FFFF,也不得落在 UTF-16 代理碼位範圍 U+D800–U+DFFF 上。任何違規都是畸形序列。

要看這套程序實際運作,從分符號(¢)的兩個位元組 UTF-8 表示來解碼:

  • C2 = 11000010 — 前導的 110 位元標示兩個位元組的序列,留下純量位元 00010。
  • A2 = 10100010 — 前導的 10 位元標示延續位元組,留下純量位元 100010。
  • 把酬載位元組合起來:00010 100010 = 00010100010 = 0xA2 = U+00A2 = ¢。

每個格式正確的 UTF-8 序列都遵循完全相同的範本,這也是小型剖析器能毫無歧義地還原數十億個字元的原因。

解碼器接受的輸入格式

點選轉換按鈕之前,確認記法符合你的意圖。UTF-8 Encoder / Decoder 把三種記法當成同一份位元組陣列的不同顯示表示——從十六進位切到十進位再切到二進位,並不改變底層 UTF-8 序列,只改變寫法。

接受的輸入規則刻意收窄,讓剖析器永遠不必猜測多餘字元可能代表什麼:

記法接受的詞元形狀¢ 的例子(U+00A2 = C2 A2)
十六進位一段連續的偶數長度字串,或以空白/逗號分隔、可帶選用 0x 前綴的一位或兩位數字詞元C2 A2, c2 a2, 0xC2 0xA2, C2,A2, 或 C2A2
十進位範圍 0–255 的整數詞元194 162
二進位每個詞元恰好八個 0 或 1 字元,以空白分隔11000010 10100010

若十六進位字串的數字個數為奇數,剖析器會拒絕。若二進位詞元短於或長於八個字元,會被拒絕。若十進位詞元不是整數,或落在 0–255 之外,會被拒絕。空白輸入解碼成空白文字——這是唯一的靜默路徑。輸入上限為文字 200,000 個 UTF-16 碼元,以及已解碼記法 200,000 個位元組,因此剖析器會拒絕更大的輸入,而不是截斷。這些緊密規則讓解碼器能毫無歧義地信任它所處理的每一個位元組。

如何把 UTF-8 位元組解碼回文字

先把一段短而已知的樣本貼進 UTF-8 Encoder / Decoder,確認記法與結果如預期運作,再處理真正的酬載。

  1. UTF-8 位元組轉文字 於操作選擇器中,再選十六進位、十進位或二進位,以符合來源的記法。
  2. 把位元組詞元貼進輸入欄,遵循上面的格式規則:偶數長度十六進位、十進位 0–255,或八位元二進位。
  3. 選轉換按鈕。解碼器剖析詞元、套用致命 UTF-8 驗證,然後要嘛顯示還原的文字,要嘛回報指向畸形位元組的明確錯誤。
  4. 把結果面板回報的位元組數量與來源交叉核對。若你貼了 C2 A2,應看到消耗兩個位元組、還原一個 Unicode 碼位。
  5. 對敏感資料做往返:拿還原的文字,把操作切到 文字轉 UTF-8 位元組, 並確認輸出與原始位元組序列完全相符。
  6. 只有往返成功之後,才該把解碼文字當成原始位元組的忠實替代。

整段操作都留在目前瀏覽器分頁內,因此沒有任何東西被上傳、紀錄、儲存、正規化、翻譯、為其他情境跳脫,或自動複製。

為什麼致命解碼勝過靜默替換

許多預設 UTF-8 解碼器——包括設為非嚴格錯誤的 Python bytes.decode(),以及建構時沒有 fatal: true 的 JavaScript TextDecoder——面對畸形輸入會插入替換字元 U+FFFD 並繼續。這種行為對隨手瀏覽很方便,但目標若是驗證一份位元組傾印確實是有效 UTF-8,就很危險。

UTF-8 Encoder / Decoder 以 fatal: true 設定瀏覽器的 TextDecoder,因此下列類型的畸形輸入會以明確錯誤失敗,而不是產出滿是替換字形的字串:

  • 過長編碼,例如 C0 AF,試圖用兩個位元組表示已經能放進一個位元組的碼位。
  • 截斷序列,例如 E2 82,三個位元組的前導之後沒有延續位元組。
  • 孤立的延續位元組,例如 A2 單獨出現、沒有前導位元組。
  • 代理編碼,例如 ED A0 80 試圖編碼 U+D800。
  • 超過 U+10FFFF 的值,超出 Unicode 純量上限。

當你看到錯誤而不是滿是 � 標記的字串,就知道那些位元組不是有效 UTF-8。下一步是辨識實際編碼——Windows-1252、Shift JIS、GBK,或 ISO-8859 家族成員——而不是硬把位元組塞進 UTF-8,假裝結果已核對。

先對已知樣本做往返

看起來合理的解碼文字,並不等於可證明與來源相同的解碼文字。在用解碼輸出覆寫任何原始資料之前,先做往返檢查:把還原的文字再編碼回位元組,並把每一個位元組與起始序列比對。

用一段短而廣為人知的樣本。美元符號 U+0024 是最簡單的情況:

  • 已知 UTF-8 位元組:24(十六進位)、36(十進位),或 00100100(二進位)。
  • 解碼成文字——結果應是單一字元 $.
  • 切到文字轉位元組,貼上 $, 選相同記法,再執行轉換。
  • 輸出應再次是 24、36 或 00100100,逐位元組相同。

若往返在任何一點失敗,要嘛原始位元組序列一開始就不是有效 UTF-8,要嘛兩次操作之間的記法選擇不一致。兩種診斷都有價值,若解碼器靜默換上替換字元,兩者都做不成。對多位元組檢查,用分符號(U+00A2 = C2 A2)、歐元符號(U+20AC = E2 82 AC),或露齒笑臉(U+1F600 = F0 9F 98 80)重複同一程序。在信任未知傾印之前,務必從小處開始。

UTF-8 不是 Base64、URL 或 HTML 編碼

UTF-8 位元組常與網頁情境裡出現的其他幾種位元組表示混淆。每種編碼服務不同的傳輸目的,不可互換:

表示它編碼什麼用途
UTF-8 位元組對應到 1–4 個位元組的 Unicode 純量值檔案儲存、網路協定、原始碼
Base64任意位元組對應到 64 字元字母表把二進位嵌進僅文字通道
URL 百分比編碼位元組編碼成 %HH,以便在 URL 中安全傳輸查詢字串、路徑區段
HTML 實體字元編碼成 &name; 或 &#nnn;HTML 標記中的保留或不可見字元
十六進位數值以 16 進位寫成的數值顏色代碼、記憶體位址、識別碼

若輸入以 iVBORw0KGgo 這類字母開頭,你看到的是 Base64,不是 UTF-8 十六進位。若以 %E2%82%AC 開頭,你看到的是 UTF-8 位元組的 URL 百分比編碼,不是位元組本身。把百分比編碼字串送進 UTF-8 解碼器,會產出字面的 % 字元,而不是原始文字。

常見純量的參考位元組序列

為了錨定你應預期看到的位元組模式,以下是八個廣為人知 Unicode 純量的正規 UTF-8 編碼,此工具用作錨點,並記載於 Unicode 標準:

純量意義UTF-8 位元組(十六進位)
U+0024美元符號($)24
U+0041字母 A41
U+007F最後一個單一位元組純量(DEL)7F
U+00A2分符號(¢)C2 A2
U+0800第一個三個位元組純量邊界E0 A0 80
U+20AC歐元符號(€)E2 82 AC
U+1F600露齒笑臉(😀)F0 9F 98 80
U+10FFFFUnicode 純量上限F4 8F BF BF

解碼其中任何一個時,你應剛好得到第二欄顯示的字元——沒有替換字形、沒有填充、沒有多餘空白。若結果不同,輸入位元組要嘛打錯、記法不對,要嘛一開始就不是 UTF-8。

若你正在權衡方案,XOR 密碼計算機:線上加密與解密文字 有詳細說明。

若你正在權衡方案,批次 ASCII 代碼轉換器:把長篇貼上編碼成十進位 有詳細說明。