Base100 會將你文字中的每一個 UTF-8 位元組編碼為 U+1F3F7 到 U+1F4F6 之間的單一碼點,因此編碼大量文字意味著每個位元組都會產生一個位於 emoji 範圍的符號,沒有填補符、分隔符、校驗碼或壓縮。整個對應過程都在你的瀏覽器中執行,而工具會在任一方向上將輸入限制在 500,000 位元組或符號以內,如此一來失控的貼上內容就不會凍結分頁。由於規則純粹以位元組為基礎,產生的符號串大小取決於原始輸入的 UTF-8 位元組數,而不是你輸入的字元、詞或字形叢集的數量。普通的 ASCII 文字會為每個字元產生一個符號,但帶有腔調字元的字母、CJK 字元和 emoji 會展開成多個 UTF-8 位元組,因而對應到多個 Base100 符號。這就是為什麼一份 10,000 字元的拉丁字母文件編碼後大約是 10,000 個符號,而一份 10,000 字元的 CJK 文章通常會編碼為 30,000 個以上。當你需要為大量文字取得可預期的尺寸關係時,唯一可靠的依據只有輸入的位元組數。

base100 encode large text
Base100 編碼大量文字:UTF-8 展開與限制

位元組對應如何隨輸入大小而擴展

Base100 的公式很直觀:對於文字 UTF-8 表示中的每個位元組 b,編碼器會輸出碼點 U+1F3F7 加上 b。位元組 0 會變成 U+1F3F7,位元組 1 會變成 U+1F3F8,位元組 255 會變成 U+1F4F6,因此該範圍橫跨輔助多語言平面上正好 256 個連續的碼點。這個對應沒有標頭、長度標記、填補符,也沒有校驗碼,這代表輸出中的每個符號都承載資訊:改動任何一個符號,就會恰好改變原始文字的一個位元組。要看這個公式如何運作,可以拿 ASCII 字母 "A" 為例,它的 UTF-8 位元組是 65。把這個值加到偏移量上:U+1F3F7 + 65 = U+1F438。所以 "A" 會編碼為 U+1F438,而解碼時則減去 65 以還原位元組。由於規則純粹是算術運算,因此沒有查找表、字母集或填補符需要管理,而且同一個位元組永遠會產生同一個符號。

正是這種算術上的簡潔,讓 Base100 在處理大量文字時表現得可預期。輸出長度等於輸入位元組數,除了這種一對一的對應之外,不會再有膨脹或壓縮。當你打算使用瀏覽器內的工具對大量文字進行 base100 編碼時,實際要問的問題是你的文字在 UTF-8 編碼後實際包含多少位元組,因為正是這個數字決定了輸出長度,也決定了你是否會撞上 500,000 符號的上限。

為什麼非 ASCII 文字會讓輸出膨脹

Base100 計算的是位元組,而不是字元,這個區別正是大量文字在編碼時會變大的主要原因。你在螢幕上看到的 Unicode 字元,會根據其碼點值編碼為 1、2、3 或 4 個 UTF-8 位元組,而這些位元組中的每一個都會變成一個 Base100 符號。因此,一段使用非拉丁字母的短字串,編碼後的 Base100 串可能會比一段較長的純 ASCII 字串更長。

輸入字元類型每個字元典型的 UTF-8 位元組數每個字元的 Base100 符號數相較於 ASCII 的輸出成長
純 ASCII (U+0000 到 U+007F)1 個位元組1 個符號基準 (1.0x)
雙位元組 UTF-8 字元 (U+0080 到 U+07FF)2 個位元組2 個符號2 倍大
大多數 CJK、阿拉伯文、擴充斯拉夫文 (U+0800 到 U+FFFF)3 個位元組3 個符號3 倍大
輔助平面字元與 emoji (U+FFFF 以上)4 個位元組4 個符號4 倍大

這個表格中的位元組數,來自 UTF-8 規範對每個範圍的定義,並記錄在 WHATWG 編碼標準中。任何特定字串的實際位元組數,則取決於其中出現的精確碼點。一份含有腔調字元的法文履歷、一篇日文文章,以及一部俄文小說,都會依據這些區段來膨脹,人們有時在幾乎是 ASCII 的文字中插入的小型 emoji 圖示也是如此。如果你的大量文字是混合內容,估算 Base100 輸出大小最簡單的方式,就是直接計算輸入的 UTF-8 位元組,而不是計算可見字元數。

如何對大量文字進行 base100 編碼

編碼器遵循三個明確的步驟,依序執行這些步驟正是讓大量貼上內容保持整潔的原因。每一步都直接對應到有文件記載的產品行為,而非推論而來的行為。

  1. 開啟 Base100 編碼器 / 解碼器,選擇「文字轉 Base100」模式,貼上或輸入你想要編碼的 UTF-8 文字,然後執行編碼器。每個 UTF-8 位元組都會透過 U+1F3F7 加上該位元組值的公式,對應到 U+1F3F7 到 U+1F4F6 範圍內的一個碼點。
  2. 原樣複製產生的符號串。不要插入空白、不要加入換行,也不要讓聊天應用程式或編輯器在複製過程中加入變體選擇器或其他裝飾性碼點。
  3. 若要反轉這個過程,將工具切換到「Base100 轉文字」,貼上未經修改的符號串,然後執行解碼器。如果任何符號落在正確範圍之外,或是還原後的位元組無法構成有效的 UTF-8 序列,解碼器會回報錯誤,而不是產生部分或不完整的字串。

對大量貼上內容而言,與少量內容唯一的操作差異在於:你應該預期輸出長度大約等於輸入的 UTF-8 位元組數,而且在開始之前就應該先預先規劃好 500,000 符號的上限。任何在複製過程中改動符號串的行為,都會讓嚴格的解碼失敗,這是刻意設計,而不是錯誤。

在 500,000 符號上限內運作

這個頁面對文字輸入強制設定 500,000 位元組的限制,並對 Base100 輸入強制設定 500,000 符號的限制,因此兩端的上限是對稱的。空白的輸入會被拒絕,輸出絕不會被靜默截斷,而這個邊界會在任何耗資源的作業執行之前先進行檢查。實際上,這代表一份大小約 500 KB 以內的 UTF-8 文字文件,可以一次完成編碼,這足以涵蓋大多數文章、程式碼檔案、組態傾印以及書籍章節,而不必切割。如果你需要編碼超過 500,000 位元組的內容,請將輸入切割成各自低於上限的區塊,然後在接收端把產生的符號串串接起來,再逐一解碼各個區塊。切割是安全的,因為對應關係完全是局部的:沒有任何區塊帶有標頭或頁尾,而解碼器會透過讀取碼點並獨立驗證 UTF-8 來重建文字。

請記住,這個限制適用於文字的位元組數,而不是字元數,所以一份 500,000 字元的 ASCII 檔案可以輕鬆納入,但一份 500,000 字元、每個字元約 3 個位元組的 CJK 檔案就會超出上限。當貼上內容接近上限時,請在編碼前先進行修剪,而不是依賴工具來處理溢位,因為工具會拒絕輸入,而不是產生部分結果。

將大量 Base100 串解碼回文字

解碼是同一個位元組公式的反向運算。解碼器以 Unicode 碼點而非 UTF-16 碼元來讀取輸入,這一點很重要,因為 Base100 位於輔助平面,在較舊的字串 API 中,一個 JavaScript 字元並不等於一個碼點。每個符號都必須落在 U+1F3F7 到 U+1F4F6 的含括範圍內,其位元組值則是透過減去 U+1F3F7 來還原。在收集完所有位元組後,嚴格的 UTF-8 解碼器會重建文字,任何無效的位元組序列都會導致嚴重錯誤,而不是出現靜默的替換字元。

這種嚴格的行為對大量文字來說很重要,因為透過即時通訊軟體、富文字編輯器或正規化管線複製時,可能會插入變體選擇器、零寬連字號、軟連字號或零星的標點符號,這些在螢幕上看起來相似,但會破壞位元組運算。一段貼上後解碼出亂碼或完全解碼失敗的符號串,幾乎都代表這個符號串在傳輸過程中被改動了。若要還原原始文字,請透過純文字管道從編碼器重新複製符號串,並直接貼到解碼器中,不要讓任何中介工具對其重新格式化。如果你能掌控兩端,請優先使用原始碼點,而不是視覺上相似的替代品,因為跨作業系統和字型的渲染會有所不同,但符合規範的字串內部的數學對應關係並不會改變。

何時其他編碼更適合大量文字

Base100 是一種可逆的位元組編碼,而不是壓縮、加密或傳輸格式,因此它並不總是處理大量文字的最佳選擇。如果目的地僅支援 ASCII,那麼 Base64、base64url、Base32、Base58 或純十六進位會在更多系統中不受干擾地傳輸,因為 Base100 的符號位於 emoji 範圍,而某些伺服器、終端機和搜尋引擎可能會將其去除或正規化。如果目標是讓檔案更小,Base100 並不會縮減資料;輸出的大小至少和 UTF-8 輸入一樣大,而且對於非 ASCII 文字來說往往更大,因此像 gzip 這類壓縮工具會產生短得多的結果。如果目標是保密或偵測竄改,Base100 完全不合用,因為任何知道這個對應關係的人都能還原位元組,而且沒有校驗碼可以偵測修改;在這種情況下請使用經過審核的加密或已認證的格式。

不過,對於謎題訊息、展示用途,以及目標是讓承載內容在視覺上與眾不同的情境來說,用於大量文字的 Base100 編碼運作方式完全符合該位元組對應的描述,而瀏覽器內的 Base100 編碼器 / 解碼器會將轉換保留在本機,因此沒有任何貼上內容會被上傳。原本的 Adam Niederer Base100 專案在 GitHub 上記錄了這個 emoji 對應,而 WHATWG 編碼標準則定義了文字邊界上解碼器所依賴的 UTF-8 行為。

如果你正在權衡各種選項,《線上 Gzcompress 大量文字:處理大型 UTF-8 承載內容》對此有詳細說明。

如果你正在權衡各種選項,《二元到文字 初學者指南:第一小時逐步講解》對此有詳細說明。