в UTF-8 декодирования в Java
Я пытаюсь передать параметры со среднего уровня PHP на Java-сервер, который понимает J2EE. Я пишу код контроллера в Groovy. Там я пытаюсь декодировать какой-то параметр, который, вероятно, будет содержать международные символы.
Я весьма озадачен результатами моего отладки этой проблемы до сих пор, поэтому я хотел поделиться этим с вами в надежде, что кто-то сможет дать правильную интерпретацию результатов.
ради меня маленький тест, параметр, который я передаю, - "déjeuner". На всякий случай, система.из.println ("déjeuner") правильно дает мне:
déjeuner
в консоли
теперь ниже приведены значения char/dec и hex каждого символа исходной строки:
next char: d 100 64
next char: ? -61 c3
next char: ? -87 a9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72
обратите внимание, что последовательность C3A9 в UTF-8 является желаемым символом:http://www.fileformat.info/info/unicode/char/00e9/index.htm
теперь, если я попытаюсь прочитать эту строку как UTF-8 строку, как в инструкции.getBytes ("UTF-8"), я внезапно получаю последовательность 11 байтов, как показано ниже:
64 c3 83 c2 a9 6a 65 75 6e 65 72
тогда как stmt.getBytes ("iso-8859-1") дает мне 9 байт:
64 c3 a9 6a 65 75 6e 65 72
обратите внимание на последовательность c3a9 здесь!
теперь, если я попытаюсь преобразовать последовательность UTF-8 в UTF-8, как в
new String(stmt.getBytes("UTF-8"), "UTF-8");
Я:
next char: d 100 64
next char: ? -61 c3
next char: ? -87 a9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72
обратите внимание на последовательность c3a9
пока
new String(stmt.getBytes("iso-8859-1"), "UTF-8")
результаты:
next char: d 100 64
next char: ? -23 e9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72
Примечание э9 который в utf-8 (и ascii) снова является символом "é", которого я жажду.
к сожалению, ни в одном случае я не заканчиваю правильную строку, которая будет отображаться как литеральная строка "déjeuner". Как ни странно, последовательности байтов кажутся правильными.
4 ответов
при работе со строками, всегда помните: byte
!= char
. Так в вашем первом примере, у вас есть char c3
, а не byte c3
что огромная разница:byte
будет частью последовательности UTF-8, но char
уже является Unicode. Поэтому, когда вы преобразуете это в UTF-8, символ Unicode c3
должны стать byte
последовательность c3 83
.
Итак, вопрос: Как вы получили строку? В этом коде должна быть ошибка, которая не правильно обрабатывать кодировку UTF-8 byte
последовательности.
почему ISO-8859-1
обычно работает так, что эта кодировка не изменяет char
с кодовой точкой byte последовательности не изменен.
ваш последний пример также неверен:char e9
это é в ISO-8859-1
и Unicode. В UTF-8 это недопустимо, так как это не byte
и с byte c3
префикс отсутствует. Тем не менее, это правильно представляет строку Юникода, которую вы ищете.
если вы начинаете со строки Java, где "d\u00C3\u00A9jeuner".equals(stmt)
тогда данные уже повреждены на этом этапе.
На Java char
не является C char
. А char
в Java имеет ширину 16 бит и неявно содержит UTF-16 закодированных данных. Попытка сохранить любые другие закодированные данные в Java char
/ String тип напрашивается на неприятности. Символьные данные в любой другой кодировке должны быть как byte
данные.
если Вы читаете с помощью сервлета В API, то вполне вероятно, что HTTP-запрос содержит несогласованную или недостаточную информацию о кодировке. Проверьте вызывающий код и заголовки HTTP. Вполне вероятно, что клиент кодирует данные как UTF-8, но сервлет декодирует его как ISO-8859-1.
у меня очень похожая проблема, за исключением того, что моя форма использует запрос "GET", а не запрос "POST".
Итак, мой URL-адрес что-то вроде: http://localhost:4502/form.jsp?query=d%C3%A9jeuner
request.getCharacterEncoding() = ISO-8859-1
response.getCharacterEncoding() = UTF-8
request.getParameter("query") = déjeuner
поэтому HttpServletRequest должен использовать UTF-8 для декодирования запроса param (что явно не так) или это просто ошибка браузера, потому что браузер не устанавливает заголовок кодировки символов (что опять же не имеет большого смысла, потому что это не делает запрос post.) Вот полный набор заголовков И обратите внимание на %C3%A9 в URL-адресе.
http://localhost:4502/form.jsp?query=d%C3%A9juerne
GET /form.jsp?query=d%C3%A9juerne HTTP/1.1
Host: localhost:4502
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
эта проблема заключается в том, что я фактически скопировал и вставил запрос в форму браузера, и он неправильно закодировал его. Как в chrome, так и в firefox.
после небольшого исследования я нашел этот ответ
как заставить UTF-8 работать в Java webapps?.
речь идет о настройке URIEncoding= "UTF-8"в соединителе tomcat.
теперь, чтобы выяснить, как это сделать в CMS, которую мы используем (CQ5/Day).