25

Javascriptで、文字列にマルチバイト文字が含まれているかどうかを検出することはできますか?もしそうなら、どれを知ることは可能ですか?

私が遭遇している問題はこれです(Unicode文字が正しく表示されない場合はお詫びします)

s = "";

alert(s.length);    // '2'
alert(s.charAt(0)); // '��'
alert(s.charAt(1)); // '��'

ここで少し明確にするために編集してください(私は願っています) 私が今理解しているように、Javascriptのすべての文字列は一連のUTF-16コードポイントとして表されます。つまり、通常の文字は実際には2バイト(16ビット)を占めるため、タイトルでの「マルチバイト」の使用は少しでした。オフ。上記の例の文字列など、一部の文字は基本多言語面(BMP)に該当しないため、2つのコードポイント(32ビット)を使用します。それが私が尋ねていた質問です。私は元のタイトルも編集していません。なぜなら、このことについてあまり知らない人(したがって、SOで情報を検索する人)にとって、「マルチバイト」は理にかなっているからです。

4

1 に答える 1

34

JavaScript文字列はUCS-2でエンコードされますが、 2つの16ビット数(UTF-16サロゲートペアU+0000)を使用して、基本多言語ペイン( -U+D7FFおよびU+E000- )の外側のUnicodeコードポイントを表すことができます。最初の数は-の範囲内である必要があります。U+FFFFU+D800U+DFFF

これに基づいて、文字列に基本多言語面の外側にある文字が含まれているかどうかを簡単に検出できます(これは私が求めていることです:文字列に範囲外にある文字が含まれているかどうかを識別できるようにする必要がありますJavaScriptが単一の文字として表すコードポイントの数):

function containsSurrogatePair(str) {
    return /[\uD800-\uDFFF]/.test(str);
}

alert( containsSurrogatePair("foo") ); // false
alert( containsSurrogatePair("f") ); // true

文字列に含まれるコードポイントを正確に把握するのは少し難しく、UTF-16デコーダーが必要です。以下は、文字列をUnicodeコードポイントの配列に変換します。

var getStringCodePoints = (function() {
    function surrogatePairToCodePoint(charCode1, charCode2) {
        return ((charCode1 & 0x3FF) << 10) + (charCode2 & 0x3FF) + 0x10000;
    }

    // Read string in character by character and create an array of code points
    return function(str) {
        var codePoints = [], i = 0, charCode;
        while (i < str.length) {
            charCode = str.charCodeAt(i);
            if ((charCode & 0xF800) == 0xD800) {
                codePoints.push(surrogatePairToCodePoint(charCode, str.charCodeAt(++i)));
            } else {
                codePoints.push(charCode);
            }
            ++i;
        }
        return codePoints;
    }
})();

alert( getStringCodePoints("f").join(",") ); // 102,119558
于 2011-02-03T10:36:31.870 に答える