UTF-8 是一種由 RFC 3629 標準化的可變長度 Unicode 編碼,每個純量值使用 1 到 4 個位元組,其中 U+0000 到 U+007F 的 ASCII 碼位仍保持單一位元組,而 U+FFFF 以上的輔助字元則需要 4 個位元組。因此,UTF-8 解碼速查表同時是三件事的精簡參考:標示序列長度的起始位元組範圍、將碼位打包進這些位元組的位元模式,以及嚴格解碼器所接受的輸入表示法格式 — 十六進位、十進位和二進位。掌握這三項參考後,解碼就不再是憑直覺,而是成為一個可驗證的操作,會拒絕格式錯誤的輸入,而不是以 U+FFFD 取代字元悄悄替換。以下速查表列出四種 UTF-8 序列形狀、可壓力測試每個解碼器的八個邊界碼位、UTF-8 編碼器 / 解碼器所接受的表示法格式,以及確認輸出與來源逐位元組相同的來回轉換工作流程。

utf8 decode cheat sheet
UTF-8 解碼速查表:模式與表示法參考

UTF-8 位元組模式參考

UTF-8 位元組序列是由一個宣告總長度的起始位元組,加上零到三個接續位元組所構成。起始位元組的高位元並非任意設定;它們直接對應到純量值的範圍,這就是為什麼單一十六進位數字常常就能告訴你單一位元組字元是否足夠。底下的模式表是任何 UTF-8 解碼速查表的核心,因為無論是瀏覽器、程式語言或十六進位編輯器中的解碼器,都會將同一列套用於同一個起始位元組。

碼位範圍位元組數起始位元組接續位元組
U+0000 – U+007F10xxxxxxx無
U+0080 – U+07FF2110xxxxx10xxxxxx
U+0800 – U+FFFF31110xxxx10xxxxxx (×2)
U+10000 – U+10FFFF411110xxx10xxxxxx (×3)

下方八個邊界碼位可測試模式表中的每個轉換。每個項目顯示純量值、十六進位位元組序列,以及該序列所觸發的規則。它們來自 UTF-8 編碼器 / 解碼器所使用的文件化測試集,對應 RFC 3629 的邊界。

  • U+0024 ($) → 24 — ASCII 單位元組;十六進位與 ASCII 數字完全一致。
  • U+0041 (A) → 41 — ASCII 單位元組;與貨幣符號的觀察相同。
  • U+007F (DEL) → 7F — 雙位元組範圍開始前的最後一個單位元組值。
  • U+00A2 (¢) → C2 A2 — 雙位元組序列;起始位元組為 C0 或更高代表多位元組序列開頭。
  • U+20AC (€) → E2 82 AC — 三位元組序列;起始位元組以位元 1110 開頭。
  • U+1F600 (😀) → F0 9F 98 80 — 四位元組序列;輔助平面,起始位元組以 11110 開頭。
  • U+0800 — 第一個三位元組邊界;從此開始的值需要三個或更多位元組。
  • U+10FFFF → F4 8F BF BF — 最大純量值;標準中最後一個有效的四位元組序列。

十六進位、十進位與二進位表示法比較

同一個底層 UTF-8 位元組序列可以用三種不同方式書寫。只顯示十六進位的速查表會讓讀者在面對十進位或二進位的來源時束手無策,因此下表記錄了嚴格解碼器對各種表示法強制執行的規則。切換表示法並不會改變位元組,只是改變它們的顯示方式。

表示法輸出格式接受的輸入
十六進位以空格分隔的大寫兩位數位元組以空格或逗號分隔的一位或兩位十六進位 token,選擇性加上 0x 前綴,或一個連續偶數長度的十六進位字串
十進位以空格分隔的 0–255 整數值僅限整數 token,每個位元組一個
二進位每個位元組恰好八個 0/1 數字每個 token 恰好八個 0 或 1 字元

這些是同一個位元組陣列的不同顯示方式。像 E282AC 這樣的連續十六進位字串之所以可被接受,是因為它包含偶數位數,而 E282A 則會因格式錯誤而被拒絕。十進位輸入會拒絕任何不在 0–255 範圍內的 token,二進位輸入則會拒絕任何長度不恰好為八個字元的 token。空輸入解碼為空文字。

解碼錯誤及其意義

嚴格的解碼器會在五類格式錯誤的輸入上失敗,而不是產生 U+FFFD 取代字元。認識每一類錯誤的位元組特徵是速查表的一部分,因為它能告訴你該修正來源中的什麼地方,而不是盲目信任輸出。

  • 過長編碼(例如 C0 AF):同一純量值使用比必要更多的位元組編碼,由 RFC 3629 所禁止。
  • 截斷序列(例如 E2 82):多位元組序列在所有接續位元組出現之前就被切斷。
  • 孤立接續位元組:符合模式 10xxxxxx 但前方沒有有效起始位元組的位元組。
  • 代理編碼:將 U+D800 到 U+DFFF 範圍的值編碼為 UTF-8,即使代理純量值已被保留。
  • 超出範圍值:任何會解碼為超過 U+10FFFF(最高允許純量值)的序列。

當這類錯誤被觸發時,輸入會被整體拒絕。解碼器不會嘗試復原,也不會顯示取代字符彷彿它們是原始文字。這就是為什麼來回轉換檢查具有意義:嚴格解碼會告訴你這些位元組是否真的屬於 UTF-8,或者它們不是。

使用工具解碼 UTF-8 位元組

  1. 開啟 UTF-8 編碼器 / 解碼器,選擇「UTF-8 位元組轉文字」方向。
  2. 選擇十六進位、十進位或二進位表示法,讓解析器符合輸入的格式。
  3. 依照選定表示法的嚴格規則,將位元組貼入輸入欄位 — 連續偶數長度的十六進位、分隔的 token,或八位元的二進位群組。
  4. 選擇轉換按鈕以執行嚴格解碼,並在結果面板中讀取輸出。
  5. 比對結果面板所回報的位元組數與你所提供的位元組數,然後將結果重新編碼回位元組,並檢查是否完全相符。

反向操作則處理編碼。選擇「文字轉 UTF-8 位元組」、挑選輸出的表示法、貼上 Unicode 文字,然後選擇轉換按鈕。編碼器會拒絕不成對的 UTF-16 代理碼位,因此聲稱無損的轉換並不會悄悄改變你的輸入。代表輔助字元的有效代理配對則會被正常接受。

以單一計算為例,下方的歐元符號追蹤展示如何從一個碼位建構三位元組序列。U+20AC 有 16 個有效位元:0010 0000 1010 1100。三位元組模板為 1110xxxx 10xxxxxx 10xxxxxx,因此位元分成 4、6、6 三組。代入後得到 11100010 10000010 10101100,以十六進位表示即為 E2 82 AC — 與上方邊界參考中所列的位元組序列相同。十進位 226 130 172 與二進位 11100010 10000010 10101100 是同一三個位元組的不同表示法。

替換資料前的來回轉換驗證

解碼只有在將結果重新編碼後能重現原始位元組時才值得信賴。使用 UTF-8 編碼器 / 解碼器時,這代表將位元組輸入解碼為文字、複製該文字、再以相同的表示法將其編碼回位元組,然後比對兩個位元組序列是否完全相符。200,000 UTF-16 碼位的輸入上限與 200,000 位元組的解碼表示法上限,是為了讓這項驗證保持回應迅速,因此請從一個簡短的已知樣本開始,再逐步擴大。

在來回轉換相符之前,請保留一份原始資料。如果位元組是像 Windows-1252 或 Shift JIS 這類舊式內容,解碼將會失敗,而這個失敗本身就是資訊:它告訴你來源並非 UTF-8。強行將舊式位元組通過 UTF-8 解碼器只會掩蓋真正的編碼,因此請先識別實際編碼,再重新編碼。

在驗證過程中,所有文字與位元組都會保留在目前的分頁中。不會自動上傳、記錄、儲存、正規化、翻譯、跳脫或複製。這種僅限本機的行為讓檢查對敏感內容是安全的,但這也代表你必須自行保留來源位元組,然後才能在任何流程中替換它們。對於超過輸入上限的資料,或二進位檔案,請使用專門的二進位工具,而不是此解碼器。

延伸閱讀:透過選擇來源編碼轉換為無 BOM 的 UTF-8。

延伸閱讀:Linux 上的 Base32 解碼:瀏覽器式的替代方案。