[英]How can a 3-byte wide UTF-8 character only use a single UTF-16 code unit?
從這個參考:
它指出 string.length 的值實際上是 UTF-16 代碼單元的數量,而不是字符數。
我顯然天真地假設任何 3 或 4 個字節寬的 UTF-8 字符都必須占用 2 個 UTF-16 代碼單元。 這就是我的意思:
我對字符串做了一些實驗: 😀œ´®†¥¨ˆøπ¬˚∆˙©ƒ∂ßåΩ≈ç√∫˜µ≤ユーザーコードa
,其中包含 1、2、3 和 4 字節寬的字符. 我得到了一些令人驚訝的結果。
每個 UTF-16 代碼單元的寬度為 2 個字節。 字符串中的字符數為 35。取字符串的 string.length 等於 36,這意味着只有一個字符占用了 2 個 UTF-16 代碼單元,但有幾個 UTF-8 字符的寬度為 3 和 4 個字節。
使用下面的代碼,我檢查了每個 UTF-8 字符、它使用的字節數以及它的 string.length。 有趣的是,所有 3 字節的 UTF-8 字符都只使用一個 UTF-16 代碼單元。 唯一需要 2 個代碼單元的字符是 4 字節寬的表情符號。
有人可以解釋一下這是怎么回事嗎? 謝謝!
代碼:
function iterateCharacters(str) {
let te = new TextEncoder();
let totalBytes = 0;
let totalCodeUnits1 = 0;
let totalCodeUnits2 = 0;
let arr = [...str];
for (let i = 0; i < arr.length; i++) {
let bytes = te.encode(arr[i]).length;
let length = arr[i].length;
totalBytes += bytes;
console.log(" i: " + i + " char: " + arr[i] + " bytes: " + bytes + " length: " + length);
// Erroneous assumption that more than 2 utf8 bytes would occupy 2 UTF-16 code units:
totalCodeUnits1 += bytes < 3 ? 1 : 2;
totalCodeUnits2 += length;
}
console.log(" total UTF-16 code units (erroneous calculation): " + totalCodeUnits1)
console.log(" total UTF-16 code units (correct calculation): " + totalCodeUnits2)
console.log(" total characters: " + arr.length)
console.log(" total UTF-8 bytes: " + totalBytes)
}
var sample = "😀œ´®†¥¨ˆøπ¬˚∆˙©ƒ∂ßåΩ≈ç√∫˜µ≤ユーザーコードa";
iterateCharacters(sample);
console.log("total number of UTF-16 code units: " + sample.length);
console.log("total number of characters: " + [...sample].length);
console.log("total number of UTF-8 bytes: " + (new TextEncoder().encode(sample)).length);
結果:
i: 0 char: 😀 bytes: 4 length: 2
i: 1 char: œ bytes: 2 length: 1
i: 2 char: ´ bytes: 2 length: 1
i: 3 char: ® bytes: 2 length: 1
i: 4 char: † bytes: 3 length: 1
i: 5 char: ¥ bytes: 2 length: 1
i: 6 char: ¨ bytes: 2 length: 1
i: 7 char: ˆ bytes: 2 length: 1
i: 8 char: ø bytes: 2 length: 1
i: 9 char: π bytes: 2 length: 1
i: 10 char: ¬ bytes: 2 length: 1
i: 11 char: ˚ bytes: 2 length: 1
i: 12 char: ∆ bytes: 3 length: 1
i: 13 char: ˙ bytes: 2 length: 1
i: 14 char: © bytes: 2 length: 1
i: 15 char: ƒ bytes: 2 length: 1
i: 16 char: ∂ bytes: 3 length: 1
i: 17 char: ß bytes: 2 length: 1
i: 18 char: å bytes: 2 length: 1
i: 19 char: Ω bytes: 2 length: 1
i: 20 char: ≈ bytes: 3 length: 1
i: 21 char: ç bytes: 2 length: 1
i: 22 char: √ bytes: 3 length: 1
i: 23 char: ∫ bytes: 3 length: 1
i: 24 char: ˜ bytes: 2 length: 1
i: 25 char: µ bytes: 2 length: 1
i: 26 char: ≤ bytes: 3 length: 1
i: 27 char: ユ bytes: 3 length: 1
i: 28 char: ー bytes: 3 length: 1
i: 29 char: ザ bytes: 3 length: 1
i: 30 char: ー bytes: 3 length: 1
i: 31 char: コ bytes: 3 length: 1
i: 32 char: ー bytes: 3 length: 1
i: 33 char: ド bytes: 3 length: 1
i: 34 char: a bytes: 1 length: 1
total UTF-16 code units (erroneous calculation): 50
total UTF-16 code units (correct calculation): 36
total characters: 35
total UTF-8 bytes: 85
total number of UTF-16 code units: 36
total number of characters: 35
total number of UTF-8 bytes: 85
(另見 Jsfiddle: https ://jsfiddle.net/Allasso/o5zpmrc9/)
UTF-16 不同於 UTF-8。 00010000(十六進制)以下的所有 Unicode 字符都可以用單個 UTF-16 字符表示。 在此之上,您會溢出到 2 個 UTF-16 字符。 然而,這意味着所有 3 字節 UTF-8 編碼都適合單個 UTF-16 字符。
請記住,UTF-8 字符的 3 個字節並沒有完全用於實際的代碼點(數字)。 一些位被“標記”位占用,向解釋軟件指示代碼序列已經開始。 UTF-16 也是如此,但方案(標記位模式)不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.