文字轉十六進位是將字串中的每個字元寫成其 UTF-8 位元組的兩位十六進位代碼的過程,因此字母「Hi」會顯示為 48 69,而表情符號 😀 則顯示為 F0 9F 98 80。這項轉換會在一個固定的三階段管線中執行:每個 Unicode 字元會先被識別為一個純量值,然後依據 WHATWG 編碼標準中定義的規則將該純量編碼成一到四個 UTF-8 位元組,接著將每個位元組寫成兩位十六進位數字。兩位一組的配對來自於一個位元組可容納 0 到 255 的數值,這正好可以放入兩個十六進位數字;高於 0x7F 的位元組則視所選的大小寫,後退為 ASCII 字母 A 到 F。輸出會保留位元組順序與字元順序,因此十六進位並非加密或雜湊——只要擁有相同的 UTF-8 位元組,任何人都能重建出相同的文字,僅受制於為對應解碼器所記錄的開頭 U+FEFF 注意事項。理解這三個階段,正是區分一個快速的十六進位傾印與一個在各種腔調字、表意文字、表情符號、NUL 位元組以及組合記號下都能值得信賴的轉換過程的關鍵。

text to hex explained
文字轉十六進位解析:UTF-8 位元組如何成為十六進位配對

UTF-8 文字如何成為十六進位

文字轉十六進位的第一階段是純量解析。JavaScript 字串是 UTF-16 碼位的序列,而格式正確的 Unicode 文字會將高位與低位代理項組合成代理配對,以表示基本多語言平面以外的字元。一組有效的配對代表一個輔助平面純量,而單獨的高位或低位代理項根本不是 Unicode 純量——WHATWG TextEncoder 標準定義了這些單獨碼位的處理方式,MDN 參考文件則記錄了對應的瀏覽器行為。

第二階段是位元組編碼。UTF-8 是一種可變寬度編碼:碼位 0 到 127 使用一個位元組,128 到 2047 使用兩個位元組,2048 到 65535 使用三個位元組,65536 到 1114111 使用四個位元組。對於任何格式正確的純量,這個對映是確定性且可逆的,這就是為什麼在輸入格式正確的前提下,十六進位是底層字串的無損檢視。

第三階段是十六進位格式化。每個位元組會被改寫為從 0-9 與 a-f(或是大寫模式中的 A-F)中取出的兩個字元。這個過程不會進行壓縮、跳脫解析、區域改寫或修剪——格式化是一個在 UTF-8 位元組陣列已經完成之後才執行的呈現步驟。編碼、調整大小、格式化、顯示與剪貼簿準備都在當前的瀏覽器分頁中於本地端完成,因此整個過程中不會上傳任何資料。

每個字元佔用多少位元組

UTF-8 的位元組寬度完全取決於碼位,而非字形。這就是為什麼一個四個字的句子,在沒有明顯規律的情況下,可能編碼為八個、十五個或更多的十六進位數字。下表列出四個寬度帶中各一個參考純量,讓規則更具體:

碼位字元位元組UTF-8 十六進位(大寫)
U+0041A141
U+00E9é2C3 A9
U+4F60你3E4 BD A0
U+1F600😀4F0 9F 98 80

配對永遠是先讀高位半位元組再讀低位半位元組,這就是為什麼 U+0041 顯示為「41」而非「14」,以及為什麼 U+00E9 跨兩個位元組顯示為「C3 A9」而非單一符號。在這個位元組到配對的對映固定之後,不同工具之間變化的不是編碼後的位元組,而僅有它們之間的分隔符與字母大小寫。

如何使用 Text To HEX 將文字轉為十六進位

Text To HEX 工具使用標準的 TextEncoder API,在你的瀏覽器中直接執行與上述相同的三階段管線,因此你可以在不上傳任何資料的情況下,從輸入的字串取得可複製貼上的十六進位配對。每當你需要為除錯、協定工作或與其他工具分享位元組而取得精確的 UTF-8 十六進位檢視時,都可以使用它。請依照下列步驟以產生可靠的結果。

  1. 在輸入欄位中輸入你的文字,包括瀏覽器欄位能容納的任何 Unicode、空白字元或 NUL 資料——編碼器會針對編碼當下欄位中所包含的字串進行運作。
  2. 從三種輸出格式中挑選一種:連續配對如 4869、以空格分隔的配對如 48 69,或帶有 0x 前綴的符記如 0x48 0x69。也可以選擇 A-F 的大小寫。
  3. 點擊編碼。工具會回報精確的 UTF-8 位元組數量、格式化後的輸出長度,以及在適當情況下,被替換為 U+FFFD 的孤立代理項數量。
  4. 如果有任何碼位被捨棄,請檢視替換警告。若沒有該警告,你的十六進位會無損地描述原始文字;若有該警告,則在解碼時無法還原原始的孤立代理碼位。
  5. 使用複製按鈕將完整的十六進位輸出複製到剪貼簿。若剪貼簿權限被拒絕,請手動選取唯讀的結果;位元組本身不會受到影響。

編輯輸入、更改格式或大小寫,或是開始新的編碼,都會清除先前的結果與任何過期的複製狀態,因此你複製的值永遠會與當下的編碼結果一致。

讀懂這三種輸出格式

這三種格式是同一個位元組陣列上的呈現選擇。純文字格式會將每個位元組的兩位數字串接起來,產生長度為 2n 的字串,其中 n 是 UTF-8 的位元組數。以空格分隔的格式會在每對之間插入一個 ASCII 空格,得到的長度為 3n 減 1,因為在第一個位元組之前與最後一個位元組之後不會再加上分隔符。帶有 0x 前綴的格式會將每個位元組寫成「0x」加上兩位數字,並以單一空格分隔各符記,長度為 5n 減 1。

這些精確的公式對輸出預算而言相當重要。Text To HEX 在格式化結果中最多接受 4,999,999 個 UTF-16 碼位,而此邊界刻意設計得相當緊:一百萬個以 0x 前綴格式輸出的 ASCII 輸入字元,正好會產生 4,999,999 個輸出碼位。在繁瑣的格式下,多位元組的 Unicode 可能會在輸入預算用盡前就達到這個上限,此時工具會拒絕請求,而不是切換格式、切割位元組或取樣內容。小寫與大寫的 A-F 會產生相同的位元組數量與相同的分隔符數量,因此字母大小寫完全不會改變格式化後的輸出長度。

編碼器會保留哪些內容,哪些又會略過不處理

Text To HEX 刻意作為 UTF-8 的一個精簡檢視層。NUL(U+0000)會成為位元組 00,並被視為與其他資料無異。CR、LF、Tab 與空格會以其原始順序編碼——不會進行換行轉換。組合序列會保持分解狀態;輸入「e」後接 U+0301 會編碼為 65 CC 81,而不會被改寫為 U+00E9 的 C3 A9。這個工具在編碼之前不會套用 Unicode 正規化、大小寫轉換、跳脫解析、區域感知改寫,或任何其他轉換。

唯一的預處理步驟是孤立代理項的替換。JavaScript 將字串以 UTF-16 儲存,因此基本多語言平面以外的字元會佔用兩個稱為代理配對的碼位。若字串中包含沒有對應配對的高位或低位代理項,它便不是 Unicode 純量,WHATWG TextEncoder 標準會指定在編碼之前將每個此類碼位替換為 U+FFFD。該替換在十六進位中顯示為 EF BF BD,並會在結果面板中明顯地計數,讓你知道在這種輸入下來回轉換不會完全精確。

十六進位來回轉換會失敗的時機

來回轉換是「文字 → 十六進位 → 文字」的過程,只有在輸入是格式正確且不以 U+FEFF 開頭的 Unicode 時才會精確。這個開頭的零寬不斷行空格注意事項之所以存在,是因為某些解碼器(包括配套的十六進位轉文字轉換器)會將開頭的 EF BB BF 視為位元組順序記號,而不是字元 U+FEFF。若你的文字以該字元開頭,並透過會消耗 BOM 的工具進行解碼,則還原後的文字將缺少第一個字元。

另外兩個常見的已記錄失敗模式也經常出現。第一,孤立的 UTF-16 代理項無法在編碼後存活,因為它會被替換為 U+FFFD;接著解碼時會得到 U+FFFD,而非你原始的碼位。第二,分解的組合序列在編碼過程中會保持分解狀態,並以分解序列的形式解碼——所謂「格式正確的來回轉換」會保留位元組形式,但不會保留視覺上的正規化。這些失敗模式除了可見的替換計數之外,並不會被特別標示出來;至於這些是否會影響你的下游消費者,則由你自行判斷。

十六進位是一種編碼的顯示方式,而非單向函式。只要擁有相同的 UTF-8 位元組,並採用遵循相同原則的解碼器,你就能重建來源字串。如需知名位元組的參考檢視,請參閱文字轉十六進位速查表——當你準備好要編碼自己的字串時,Text To HEX 工具能以連續、以空格分隔或 0x 前綴的形式,提供精確的 UTF-8 位元組檢視。

想進一步了解,請參閱大型文字的字元碼查詢:處理每個碼位。