Могу ли я зависеть от поведения charCodeAt () и fromCharCode (), чтобы они оставались прежними? - PullRequest
6 голосов
/ 05 июня 2011

Я написал личное веб-приложение, которое использует charCodeAt() для преобразования текста, введенного пользователем, в соответствующие коды символов (например, преобразуется в 8839 для хранения), которое затем отправляется наPerl, который отправляет их в MySQL.Чтобы извлечь введенный текст, приложение использует fromCharCode() для преобразования чисел обратно в текст.

Я решил сделать это, потому что с поддержкой Unicode в Perl очень трудно справиться правильно.Таким образом, Perl и MySQL видят только цифры, что делает жизнь намного проще.

Мой вопрос: могу ли я рассчитывать на fromCharCode(), чтобы всегда преобразовывать число, например 8834, в соответствующий символ?Я не знаю, какой стандарт он использует, но допустим, что он использует UTF-8, если он будет изменен для использования UTF-16 в будущем, это, очевидно, сломает мою программу, если не будет обратной совместимости.

Я знаю, что мои представления об этих понятиях не так ясны, поэтому, пожалуйста, уточните, если я показал недоразумение.

Ответы [ 6 ]

9 голосов
/ 05 июня 2011

fromCharCode и toCharCode имеют дело с Unicode кодовыми точками , то есть числами от 0 до 65535 (0xffff), при условии, что все символы находятся в базовой многоязычной плоскости (BMP).Unicode и кодовые точки являются постоянными, поэтому вы можете доверять им, чтобы они всегда оставались неизменными.

Кодировки , такие как UTF-8 и UTF-16, принимают поток кодовых точек (чисел)и вывести поток байтов.JavaScript несколько странен тем, что символы вне BMP должны создаваться двумя вызовами toCharCode, в соответствии с правилами UTF-16.Однако практически все символы, с которыми вы когда-либо сталкивались (включая китайский, японский и т. Д.), Находятся в BMP, поэтому ваша программа будет работать, даже если вы не обрабатываете эти случаи.

Одна вещь, которую вы можете сделать, этопреобразовать числа обратно в байты (в формате int16 с прямым порядком байтов) и интерпретировать полученный текст как UTF-16.Поведение fromCharCode и toCharCode исправлено в текущих реализациях JavaScript и никогда не изменится.

5 голосов
/ 05 июня 2011

Я решил сделать это, потому что с поддержкой юникода в Perl очень трудно справиться правильно.

Это ɴᴏᴛ правда!

Perl обладает самой сильной поддержкой Юникода среди всех основных языков программирования. Работать с Unicode намного проще, если вы используете Perl, чем если вы используете любой из C, C ++ , Java, C , Python, Ruby PHP или Javascript. Это не гипербола и бустеризм от необразованной, слепой верности .; это взвешенная оценка, основанная на более чем десятилетнем профессиональном опыте и учебе.

Проблемы, с которыми сталкиваются наивные пользователи, возникают практически всегда, потому что они обманывают себя в том, что такое Юникод. Самый страшный мозговой жук номер один думает, что Unicode похож на ASCII, но больше. Это абсолютно и совершенно неправильно. Как я уже писал в другом месте:

Фундаментально и критически не соответствует действительности , что Uɴɪᴄᴏᴅᴇ - это просто некоторый расширенный набор символов относительно ᴀsᴄɪɪ. В лучшем случае это верно не более, чем ошеломленный ɪsᴏ ‑ 10646. Uɴɪᴄᴏᴅᴇ включает в себя гораздо больше , что просто присваивание чисел глифам: правила сопоставления и сравнения, три формы регистров, небуквенный регистр, регистр символов с несколькими кодами, как канонические, так и совместимые составленные и разложенные формы нормализации формы сериализации, графемные кластеры, перенос слов и строк, сценарии, числовые эквиваленты, ширины, двунаправленность, зеркальное отображение, ширина печати, исключения логического упорядочения, варианты глифов, контекстное поведение, локали, регулярные выражения, множественные формы объединения классов, несколько типов разложений, сотен и сотен критически полезных свойств и многое, многое другое‼

Да, это много, но это не имеет никакого отношения к Perl. Это связано с Юникодом. Этот Perl позволяет вам получить доступ к этим вещам, когда вы работаете с Unicode, это не ошибка, а особенность. То, что эти другие языки не позволяют вам полный доступ к Unicode, никоим образом не может быть истолковано как точка в их пользу: скорее, это все основные ошибки наивысшей возможной серьезности, потому что если вы не можете работать с Unicode в 21-м веке, тогда этот язык является примитивным, сломанным и принципиально бесполезным для требовательных требований современной обработки текста.

Perl нет. И в миллиард раз легче сделать все правильно в Perl, чем на других языках; в большинстве из них вы даже не можете обойти их недостатки дизайна. Ты просто облажался Если язык не обеспечивает полную поддержку Unicode, он не подходит для этого столетия; откажитесь от него.

Perl делает Unicode бесконечно проще, чем языки, которые не позволяют использовать Unicode должным образом.

В этом ответе вы найдете вначале Семь простых шагов для работы с Unicode в Perl, а в нижней части этого же ответа вы найдете некоторый шаблонный код, который поможет. Поймите это, затем используйте это. Не принимайте разбитость. Вы должны изучить Юникод, прежде чем сможете использовать Юникод.

И вот почему нет простого ответа. Perl облегчает работу с Unicode, при условии , что вы понимаете, что такое Unicode. И если вы имеете дело с внешними источниками, вам нужно организовать, чтобы этот источник использовал какую-то кодировку.

Также прочитайте все, что я говорил о ??????????????? ??????????.Это те вещи, которые вы действительно должны понять.Еще одна проблема, связанная с нарушением правил # 49 , заключается в том, что Javascript не работает, поскольку он не обрабатывает все действительные кодовые точки Unicode одинаково, независимо от их плоскости.Javascript тоже сломан почти во всех других отношениях.Это не подходит для работы с Unicode.Просто Правило # 34 убьет вас, поскольку вы не можете заставить Javascript следовать требуемому стандарту о том, что такие вещи, как \w определены для выполнения в Юникод-регулярные выражения .

Удивительно, сколько языков совершенно бесполезно для Unicode.Но Perl определенно не один из них!

4 голосов
/ 05 июня 2011

Как указано в других ответах, fromCharCode() и toCharCode() имеют дело с кодовыми точками Unicode для любой кодовой точки на Базовой многоязычной плоскости (BMP). Строки в JavaScript кодируются UCS-2, и любая кодовая точка вне BMP представляется в виде двух символов JavaScript. Ничто из этого не изменится.

Чтобы обработать любой символ Unicode на стороне JavaScript, вы можете использовать следующую функцию, которая будет возвращать массив чисел, представляющих последовательность кодовых точек 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;
    }
})();

var str = "?";
var codePoints = getStringCodePoints(s);

console.log(str.length); // 2
console.log(codePoints.length); // 1
console.log(codePoints[0].toString(16)); // 1d306
4 голосов
/ 05 июня 2011

По-моему, не сломается .

Прочтите статью Джоэла Спольски о Юникод и кодировка символов . Соответствующая часть статьи цитируется ниже:

Каждая буква в каждом алфавиту присваивается номер консорциум Unicode, который является написано так: U + 0639. это номер называется кодовая точка . U + означает «Юникод» и цифры шестнадцатеричное. Английская буква А будет быть U + 0041.

Неважно, закодировано ли это магическое число в utf-8 или utf-16, или в любой другой кодировке. Номер останется прежним.

3 голосов
/ 05 июня 2011

Строки JavaScript - это UTF-16, это не то, что будет изменено.

Но не забывайте, что UTF-16 - это кодирование переменной длины.

0 голосов
/ 06 января 2018

В 2018 году вы можете использовать String.codePointAt () и String.fromCodePoint ().

Эти методы работают, даже если персонаж не находится в Базовой многоязычной плоскости (BMP).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...