Base100 編碼會將 UTF-8 文字的每個位元組對應到 U+1F3F7 至 U+1F4F6 範圍內的某一個 Unicode 碼點,其中輸出的碼點等於 U+1F3F7 加上該位元組的值。這表示位元組 0 會變成 U+1F3F7,位元組 65(ASCII 字母 'A')會變成 U+1F438,而位元組 255 會變成 U+1F4F6 —— 每個輸入位元組對應一個表情符號區段的符號,沒有填補字元、沒有分隔符號、沒有校驗碼,也沒有語意轉換。由於這個對應是一種純粹的位元組對符號替換,由 Adam Niederer 的原始 Base100 專案所定義,任何符合規範的解碼器都可以將串流反轉回原始位元組,再還原為原始的 UTF-8 文字。大多數的編碼失敗與隱性解碼錯誤,都來自反覆出現的少數錯誤 —— 貼上時夾帶的變體選擇器、未標明的字元數假設,以及混淆位元組與使用者所感知字元 —— 嚴格的 Base100 編碼器 / 解碼器會直接拒絕這些情況,而不是用替代字元來掩蓋問題。

base100 encode tips and common mistakes
Base100 編碼技巧:停止那些會破壞解碼的錯誤

位元組對符號的對應是如何運作的

Base100 是一套擁有 256 個符號的字母表:範圍 0 至 255 的每一個可能位元組值,都擁有 Unicode 輔助平面中專屬的碼點。轉換過程是機械式的,分為兩個階段。首先,編碼器會將輸入轉換為 UTF-8 位元組,因為 Base100 是以位元組而非 Unicode 字元為運作單位。其次,每個位元組 b 會對應到碼點 U+1F3F7 + b。這個數學公式就是整個演算法,沒有查表、沒有金鑰,除了加上固定的偏移量之外,沒有任何其他轉換。

用一個例子走過一遍就能確認這個規律。ASCII 字母 'A' 在 UTF-8 中是位元組 65,十進位的 65 就是 0x41。把它與 U+1F3F7(十進位 127,991)相加,就會得到碼點 128,056,也就是 U+1F438。解碼同一個符號時,會減去 U+1F3F7 以還原出位元組 65,再將這些位元組交由嚴格的 UTF-8 解譯器處理,就能拿回字母 'A'。因為反向操作是「先減去偏移量,再進行嚴格的 UTF-8 解碼」,即使只有一個超出範圍的碼點,或多出一個位元組,就足以讓轉換中止並回傳明確的錯誤,而不是回傳錯誤的字元。原始的 Base100 參考實作記載了相同的偏移量公式,而 WHATWG 編碼標準則定義了文字邊界處瀏覽器端的 UTF-8 行為。

乾淨的 Base100 編碼實用技巧

六個習慣能持續產出「第一次嘗試就解碼成功」的輸出。

  • 從原始來源進行編碼。重新編碼已經編碼過的 Base100 串流會產生亂碼,因為前一次輸出的每個符號本身都是一個多位元組 UTF-8 序列,會被重新對應,而不是被略過。
  • 以原始碼點複製符號。請使用能複製精確 Unicode 碼點的工具來選取輸出,而不是用螢幕擷圖或 OCR,因為每個表情符號區段的符號都必須維持在 U+1F3F7–U+1F4F6 範圍內,且不附加任何東西。
  • 追蹤的是位元組,而非字元。一段 100 字元的 ASCII 訊息會變成 100 個符號;一段 100 字元的中文訊息則會變成大約 300 個符號,因為 UTF-8 中每個 CJK 碼點佔 3 個位元組。
  • 把串流視為不透明的內容。不要為了「修正」看起來不對的符號而手動編輯,因為裝置上看到的視覺外觀未必對應到實際的碼點。
  • 維持在 500,000 個符號的上限以內。工具在編碼與解碼兩個方向都會強制這個限制,以避免不慎貼上大量內容時瀏覽器分頁凍結。
  • 盡可能在同一個工具中執行編碼與解碼。Base100 編碼器 / 解碼器採用精確的偏移量公式與嚴格的 UTF-8 驗證,這能消除混用自訂腳本和線上轉換器時所產生的飄移。

會破壞解碼的常見錯誤

大多數失敗的解碼並不神秘 —— 它們屬於一小群眾所週知的錯誤。在貼上之前先辨識出來,能省下一次來回,也能避免錯誤解碼為亂碼文字卻誤以為一切正常。

錯誤看起來是什麼樣子嚴格解碼如何回應
鍵盤自動插入的變體選擇器(U+FE0F)串流在視覺上看起來一模一樣,但每個符號多了一個碼點拒絕:U+FE0F 不在 256 個符號的範圍內
為了排版美觀而加入的空格、換行或標點串流被分成每行 10 或 20 個符號拒絕:在 Base100 中,空白字元不是定界語法
從改編版本貼上時,含有 U+1F3F7–U+1F4F6 範圍以外的碼點混合了 U+1F600 或其他表情符號的集合拒絕:位元組值會變成負數或大於 255
把它當成加密,對輸出進行「加鹽」處理符號被重新排序、交換或替換語法上會通過,但會產生錯誤的文字;沒有校驗碼會提醒你
解碼在管線中曾被重新編碼的串流輸出看起來像表情符號,但還原出來是亂碼文字拒絕:工具會回報無效 UTF-8 位元組的錯誤,而不是默默插入替代字元

前三列是迄今最常見的狀況。聊天應用程式、行動裝置鍵盤和所見即所得編輯器,經常會附加 U+FE0F 來為表情符號區段的符號上色,而產生的串流在視覺上看起來一模一樣。符合規範的解碼器會對讀到的每個碼點減去 U+1F3F7,而 U+FE0F 不在這個對應表中 —— 因此轉換會以明確的錯誤中止,而不是產生損毀的字串。同樣的邏輯也適用於不小心夾帶的空格、從程式碼區塊貼進來的換行,或任何原本不存在於輸出中的標點。空輸入會因為同樣的原因被拒絕:沒有位元組可以對應,而默默回傳空結果會掩蓋失敗的情況。

如何使用工具進行編碼與解碼

這個工具把兩個方向都放在同一個頁面中,你不必在多個網站間切換,也不必維護本機腳本。

  1. 在任何現代瀏覽器中開啟 Base100 編碼器 / 解碼器 —— 轉換過程在本地執行,不會上傳任何內容。
  2. 選擇文字轉 Base100,貼上你要編碼的 UTF-8 文字,然後執行編碼器。每個 UTF-8 位元組都會對應到一個符號,輸出是位於 U+1F3F7–U+1F4F6 範圍內的一段連續碼點串流。
  3. 用純文字複製的方式取得結果。複製時不要加入空格、換行或變體選擇器;這個對應沒有定界語法,解碼器會拒絕任何落在 256 個符號字母表之外的東西。
  4. 若要解碼,切換到Base100 轉文字,貼上未經修改的符號串流,然後執行解碼器。每個碼點都必須嚴格落在 U+1F3F7–U+1F4F6 範圍內,位元組會以減去偏移量的方式重建,再由嚴格的 UTF-8 解碼器還原為原始文字。
  5. 如果解碼器回報錯誤,最常見的原因是某個被複製的符號碼點不在範圍內 —— 通常是聊天應用程式附加的變體選擇器,或是格式化貼文夾帶的空格。請從來源串流重新複製再試一次,不要急著假設原本的編碼有問題。

什麼時候不該用 Base100

Base100 擅長一件事,而辨識何時該改用其他編碼,和正確使用它一樣重要。如果目的通道僅支援 ASCII —— 例如某些舊式電子郵件系統、特定組態欄位,或會被中介程式進行百分比編碼的 URL 格式 —— 表情符號區段的輸出無法完好地通過傳輸,因為中介程式通常會跳脫或移除 ASCII 以外的字元。在這些情況下,Base64、Base32、Base58,或十六進位會更合適,並能在通道中不夾帶表情符號區段碼點的情況下完成往返轉換。

對於任何機密性或完整性需求,Base100 也不是合適的工具。這個對應是公開的,記載在原始專案儲存庫中,任何人都能還原。Base100 串流內部沒有校驗碼,因此一個語法上有效的重新排序或替換會產生不同的位元組序列,卻在解碼時不會有任何警告。對於密碼、權杖或竄改偵測,請使用經過審核的加密與鑑別格式,例如 AES-256-GCM 工作流程,或搭配 HMAC 摘要與編碼後的酬載一起使用。

跨平台渲染與複製的陷阱

這個對應是數學性的,不會因為符號如何繪製而改變;但「渲染後的字符」與「保存下來的碼點」之間的路徑,正是大多數隱性損毀的起點。同一個碼點在一個平台上可能是彩色圖示,在另一個平台上是單色外框,在第三個平台上則是豆腐方塊;無論哪種情況,底層的純量值都相同,符合規範的解碼器仍會產生正確的位元組。風險不在於渲染,而在於某些應用程式在複製、儲存或正規化步驟中所做的轉換。

iMessage、WhatsApp、Slack 以及部分行動裝置鍵盤,會悄悄地在表情符號區段的符號後面附加變體選擇器(U+FE0F),以強制彩色渲染。Discord 和某些 Markdown 編輯器則會用零寬連接器包裹符號,或把它們換成短代碼。這些附加裝飾都不是 Base100 的一部分,嚴格的解碼器會把它們標記為超出範圍的碼點,而不是去猜測。請把任何複製下來的串流都視為可疑,除非你曾經成功解碼過一次;當解碼在沒有明顯原因的情況下失敗時,請從原始來源重新匯出。Base100 安全編碼:精確到位元組的工作流程指南中詳述了該流程的逐步做法。

如果你正在權衡各種選項,適用於真實文字、可靠的 Base64 編碼/解碼替代方案對此有深入的說明。