Юникод символы из кода в javascript для кодов> 0xFFFF - PullRequest
14 голосов
/ 27 марта 2011

Мне нужно получить строку / символ из кодировки Unicode и, наконец, поместить его в текстовый узел DOM для добавления на HTML-страницу с помощью клиентского JavaScript.

В настоящее время я делаю:

String.fromCharCode(parseInt(charcode, 16));

, где charcode - шестнадцатеричная строка, содержащая код, например "1D400".Символ Unicode, который должен быть возвращен, равен ?, но возвращается !Символы в 16-битном диапазоне (0000 ... FFFF) возвращаются, как и ожидалось.

Любые объяснения и / или предложения по исправлению?

Заранее спасибо!

Ответы [ 4 ]

20 голосов
/ 27 марта 2011

String.fromCharCode может обрабатывать только кодовые точки в BMP (т.е. до U + FFFF). Для обработки более высоких кодовых точек эта функция из Mozilla Developer Network может использоваться для возврата представления суррогатной пары:

function fixedFromCharCode (codePt) {
    if (codePt > 0xFFFF) {
        codePt -= 0x10000;
        return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
    } else {
        return String.fromCharCode(codePt);
    }
}
15 голосов
/ 27 марта 2011

Проблема в том, что символы в JavaScript (в основном) кодируются UCS-2 , но могут представлять символ вне Базовой многоязычной плоскости в JavaScript как суррогатную пару UTF-16.Следующая функция адаптирована из Преобразование punycode с символом тире в Unicode :

function utf16Encode(input) {
    var output = [], i = 0, len = input.length, value;
    while (i < len) {
        value = input[i++];
        if ( (value & 0xF800) === 0xD800 ) {
            throw new RangeError("UTF-16(encode): Illegal UTF-16 value");
        }
        if (value > 0xFFFF) {
            value -= 0x10000;
            output.push(String.fromCharCode(((value >>>10) & 0x3FF) | 0xD800));
            value = 0xDC00 | (value & 0x3FF);
        }
        output.push(String.fromCharCode(value));
    }
    return output.join("");
}

alert( utf16Encode([0x1D400]) );
9 голосов
/ 27 марта 2011

Раздел 8.4 спецификации языка EcmaScript гласит:

Когда строка содержит фактические текстовые данные, каждый элемент считается одной кодовой единицей UTF-16.Независимо от того, является ли это фактическим форматом хранения String, символы в String нумеруются по их начальной позиции элемента кода, как если бы они были представлены с использованием UTF-16.Все операции над строками (если не указано иное) обрабатывают их как последовательности недифференцированных 16-разрядных целых чисел без знака;они не гарантируют, что результирующая строка находится в нормализованной форме, а также не обеспечивают чувствительных к языку результатов.

Поэтому вам необходимо кодировать дополнительные кодовые точки как пары кодовых единиц UTF-16.

Статья «Дополнительные символы в платформе Java» дает хорошее описание того, как это сделать.

UTF-16 использует последовательностииз одной или двух 16-битных кодовых единиц без знака для кодирования кодовых точек Unicode.Значения от U + 0000 до U + FFFF кодируются в одном 16-битном блоке с одинаковым значением.Дополнительные символы кодируются в двух кодовых единицах: первый из диапазона верхних суррогатов (U + D800 до U + DBFF), второй из диапазона нижних суррогатов (U + DC00 до U + DFFF).Это может показаться похожим по концепции на многобайтовые кодировки, но есть важное отличие: значения от U + D800 до U + DFFF зарезервированы для использования в UTF-16;им не назначаются символы в качестве кодовых точек.Это означает, что программное обеспечение может сказать для каждой отдельной единицы кода в строке, представляет ли она символ из одной единицы или является ли она первой или второй единицей из символа из двух единиц.Это значительное улучшение по сравнению с некоторыми традиционными многобайтовыми кодировками символов, где значение байта 0x41 может означать букву «A» или быть вторым байтом двухбайтового символа.

В следующей таблице показаны различныепредставления нескольких символов для сравнения:

кодовые точки / кодовые единицы UTF-16

U + 0041/0041

U + 00DF / 00DF

U + 6771/6771

U + 10400 / D801 DC00

Как только вы узнаете единицы кода UTF-16, вы можете создать строку, используя функцию javascript String.fromCharCode:

String.fromCharCode(0xd801, 0xdc00) === '?'
0 голосов
/ 17 марта 2019

String.fromCodePoint(), похоже, тоже помогает. Смотри здесь .

console.log(String.fromCodePoint(0x1D622, 0x1D623, 0x1D624, 0x1D400));

Выход:

????
...