в 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).