Unicode и URI кодирование, декодирование и экранирование в JavaScript - PullRequest
2 голосов
/ 08 апреля 2010

Если вы посмотрите на эту таблицу здесь , у нее есть список escape-последовательностей для символов Юникода, которые на самом деле не работают для меня.

Например, для "% 96", который должен быть -, я получаю ошибку при попытке декодирования:

decodeURIComponent("%96");
URIError: URI malformed

Если я пытаюсь закодировать "-", я получаю:

encodeURIComponent("–");
"%E2%80%93"

Я искал в интернете и увидел эту страницу , в которой упоминаются escape и unescape с decodeURIComponent и encodeURIComponent соответственно. Кажется, это не помогает, потому что% 96 не отображается как "-", независимо от того, что я пытаюсь, и это, конечно, не сработает:

decodeURIComponent(escape("%96));
"%96"

Не очень полезно.

Как я могу получить "% 96", чтобы быть "-" с JavaScript (без жесткого кодирования карты для каждого возможного символа юникода, с которым я могу столкнуться)?

Ответы [ 3 ]

4 голосов
/ 26 мая 2013

Последовательность %XX в URI кодирует «октет», то есть восьмибитный байт.Это поднимает вопрос о том, к какому символу Unicode относится декодированный байт.Если моя память служит мне правильно, в более старых версиях спецификации URI не было точно определено, какая кодировка предполагается.В более поздних версиях спецификации URI было рекомендовано, чтобы UTF-8 был кодировкой кодировки по умолчанию.То есть, чтобы декодировать последовательность байтов, вы должны декодировать каждую последовательность %XX и затем преобразовывать полученные байты в строку, используя набор символов UTF-8.

Это объясняет, почему %96 не будетдекодирования.Шестнадцатеричное значение 0x96 не является допустимой последовательностью UTF-8.Поскольку он находится за пределами ASCII, ему потребуется специальный байт модификатора перед тем, чтобы указать расширенный символ.(Подробнее см. В спецификации UTF-8.) Оба метода JavaScript encodeURIComponent() и decodeURIComponent() предполагают использование UTF-8 (как и должно быть), поэтому я не ожидал, что %96 будет правильно декодироваться.

Персонаж, на которого вы ссылались, это U + 2013, тире.Как, черт возьми, страница, на которую вы ссылаетесь, получает черту 0x96 (десятичное 150)?Они явно не предполагают кодировку UTF-8, которая является стандартом.Они не предполагают ASCII, который не содержит этот символ.Они даже не предполагают ISO-8859-1 , которая является стандартной кодировкой, которая использует один байт на символ.Оказывается, они используют специальную кодовую страницу Windows 1252 .То есть URI, который вы пытаетесь декодировать, предполагает, что пользователь находится на компьютере с Windows, а еще хуже - на компьютере с Windows на английском (или одном из нескольких других западных языков).

Короче говоря, таблица, которую вы используете, плохая.Он устарел и предполагает, что пользователь работает в английской системе Windows.Современный и правильный способ кодирования значений, отличных от ASCII, заключается в преобразовании их в UTF-8 и последующем кодировании каждого октета с использованием %XX.Вот почему вы получили %E2%80%93, когда пытались закодировать символ, и именно этого ожидает decodeURIComponent().Используемый вами URI неправильно закодирован.Если у вас нет другого выбора, вы можете догадаться, что URI использует Windows 1252, самостоятельно преобразовать байты, а затем использовать таблицу Windows 1252, чтобы узнать, какие значения Unicode были предназначены.Но это рискованно - откуда вы знаете, какой URI использует какую таблицу?Вот почему все остановились на UTF-8.Если возможно, скажите всем, кто дает вам эти URI, чтобы правильно их кодировать.

2 голосов
/ 08 апреля 2010

Публикация в виде записи вики сообщества от Карла Хендерсона "Создание масштабируемых сайтов" В книге сказано, что можно воспроизводить значительную часть примеров. С его помощью вы можете создать специальный кейс для "-".

function escape_utf8(data) {
        if (data == '' || data == null){
               return '';
        }
       data = data.toString();
       var buffer = '';
       for(var i=0; i<data.length; i++){
               var c = data.charCodeAt(i);
               var bs = new Array();
              if (c > 0x10000){
                       // 4 bytes
                       bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
                       bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
                       bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
                   bs[3] = 0x80 | (c & 0x3F);
               }else if (c > 0x800){
                        // 3 bytes
                        bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
                        bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
                       bs[2] = 0x80 | (c & 0x3F);
             }else if (c > 0x80){
                      // 2 bytes
                       bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
                      bs[1] = 0x80 | (c & 0x3F);
               }else{
                       // 1 byte
                    bs[0] = c;
              }
             for(var j=0; j<bs.length; j++){
                      var b = bs[j];
                       var hex = nibble_to_hex((b & 0xF0) >>> 4) 
                      + nibble_to_hex(b &0x0F);buffer += '%'+hex;
              }
    }
    return buffer;
}
function nibble_to_hex(nibble){
        var chars = '0123456789ABCDEF';
        return chars.charAt(nibble);
}
1 голос
/ 08 апреля 2010

См. этот вопрос , в частности этот ответ :

существует специальный формат «% uNNNN» для кодирование кодовых точек Unicode UTF-16, вместо кодирования UTF-8 байтов

Я подозреваю, что "-" является одним из этих символов, поскольку 0x96 в таблице Ascii равно û

...