Как мне преобразовать специальные символы UTF-8 в их эквивалент iso-8859-1, используя JavaScript? - PullRequest
50 голосов
/ 22 марта 2011

Я создаю приложение javascript, которое извлекает .json файлы с помощью jquery и вставляет данные в веб-страницу, в которую они встроены.

Файлы .json кодируются с помощью UTF-8 и содержат символы с акцентомкак é, ö и å.

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

Некоторые будут использовать UTF-8, нодругие будут использовать кодировку iso-8859-1.Это, конечно, искажает специальные символы из файлов .json.

Как мне преобразовать специальные символы UTF-8 в их эквивалент iso-8859-1, используя javascript?

Ответы [ 5 ]

135 голосов
/ 22 марта 2011

На самом деле, все, как правило, хранится внутри Unicode, но не будем вдаваться в подробности.Я предполагаю, что вы получаете символические строки типа «Ã ¥ äö», потому что вы используете ISO-8859 в качестве кодировки символов.Есть трюк, который вы можете сделать, чтобы преобразовать этих персонажей.Функции escape и unescape, используемые для кодирования и декодирования строк запроса, определены для символов ISO, тогда как более новые encodeURIComponent и decodeURIComponent, которые делают то же самое, определены для символов UTF8.

escape кодирует расширенные символы ISO-8859-1 (кодовые точки UTF U + 0080-U + 00ff) как %xx (двузначный шестнадцатеричный код), тогда как кодирует кодовые точки UTF U + 0100 и выше как%uxxxx (%u, за которым следует четырехзначный шестнадцатеричный код.) Например, escape("å") == "%E5" и escape("あ") == "%u3042".

encodeURIComponent процентов кодируют расширенные символы в виде последовательности байтов UTF8.Например, encodeURIComponent("å") == "%C3%A5" и encodeURIComponent("あ") == "%E3%81%82".

Таким образом, вы можете сделать:

fixedstring = decodeURIComponent(escape(utfstring));

Например, неправильно закодированный символ «å» становится «Ã ¥».Команда выполняет escape("Ã¥") == "%C3%A5", что является двумя неправильными символами ISO, закодированными как отдельные байты.Затем decodeURIComponent("%C3%A5") == "å", где два процента кодированных байтов интерпретируются как последовательность UTF8.

Если вам по какой-то причине нужно сделать обратное, это тоже работает:

utfstring = unescape(encodeURIComponent(originalstring));

Есть ли способ отличить плохие строки UTF8 от строк ISO?Оказывается, есть.Функция decodeURIComponent, использованная выше, выдаст ошибку, если задана неправильно сформированная кодированная последовательность.Мы можем использовать это, чтобы с большой вероятностью определить, является ли наша строка UTF8 или ISO.

var fixedstring;

try{
    // If the string is UTF-8, this will work and not throw an error.
    fixedstring=decodeURIComponent(escape(badstring));
}catch(e){
    // If it isn't, an error will be thrown, and we can assume that we have an ISO string.
    fixedstring=badstring;
}
7 голосов
/ 22 марта 2011

Проблема заключается в том, что после обслуживания страницы содержимое будет в кодировке, описанной в метатеге типа содержимого. Содержимое в «неправильной» кодировке уже искажено.

Лучше всего сделать это на сервере перед обслуживанием страницы. Или, как я знаю, сказать: UTF-8 сквозной или умри .

1 голос
/ 09 октября 2015

Поскольку вопрос о том, как конвертировать из ISO-8859-1 в UTF-8 закрыт, из-за этого я собираюсь опубликовать свое решение здесь.

Проблемаэто когда вы пытаетесь получить что-либо с помощью XMLHttpRequest, если XMLHttpRequest.responseType является «текстовым» или пустым, XMLHttpRequest.response преобразуется в DOMString, и в этом случае все разбивается.После этого почти невозможно надежно работать с этой строкой.

Теперь, если содержимое с сервера - ISO-8859-1, вам придется принудительно задать ответ типа " Blob", а затем преобразовать это в DOMSTring.Например:

var ajax = new XMLHttpRequest();
ajax.open('GET', url, true);
ajax.responseType = 'blob';
ajax.onreadystatechange = function(){
    ...
    if(ajax.responseType === 'blob'){
        // Convert the blob to a string
        var reader = new window.FileReader();
        reader.addEventListener('loadend', function() {
           // For ISO-8859-1 there's no further conversion required
           Promise.resolve(reader.result);
        });
        reader.readAsBinaryString(ajax.response);
    }
}

Похоже, что волшебство происходит на readAsBinaryString , поэтому, возможно, кто-то может пролить свет на то, почему это работает.

1 голос
/ 22 марта 2011

Внутренне все строки Javascript являются Unicode (на самом деле UCS-2, подмножество UTF-16).

Если вы извлекаете файлы JSON отдельно через AJAX, то вам нужно только убедиться, чтофайлы JSON обслуживаются с правильным Content-Type и charset: Content-Type: application/json; charset="utf-8").Если вы сделаете это, jQuery уже должен был правильно их интерпретировать к тому времени, когда вы обращаетесь к десериализованным объектам.

Не могли бы вы опубликовать пример кода, который вы используете для извлечения объектов JSON?

0 голосов
/ 07 октября 2015

Вы должны добавить эту строку над вашей страницей

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...