LINUX.ORG.RU

Java. Русская заглавная буква 'И' и UTF-8


0

0

Получаю в рекуэсте строку в UTF-8. Томкатовский фильтр настроен на Cp1251 (так уж сложилось), поэтому приходится разбирать строку как массив байтов и выковыривать из неё UTF-8 содержимое. В общем всё устраивает и работает, кроме одной вещи: русская заглавная буква И не поддаётся конвертации таким образом, получаются два символа вместо одного, естественно каракули/загогулины. Может быть, кто сталкивался с таким поведением, остальные буквы работают нормально, я проверял.



    String currentValue = request.getParameter("currentValue");    
    ByteArrayInputStream bais = new ByteArrayInputStream(currentValue.getBytes());
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int b;
    while ((b = bais.read()) != -1) baos.write(b);
    currentValue = baos.toString("UTF-8").toUpperCase();
★★★★

Сорри за форматирование, вот вопрос:

Получаю в рекуэсте строку в UTF-8. Томкатовский фильтр настроен на Cp1251 (так уж сложилось), поэтому приходится разбирать строку как массив байтов и выковыривать из неё UTF-8 содержимое. В общем всё устраивает и работает, кроме одной вещи: русская заглавная буква И не поддаётся конвертации таким образом, получаются два символа вместо одного, естественно каракули/загогулины. Может быть, кто сталкивался с таким поведением, остальные буквы работают нормально, я проверял.

Bohtvaroh ★★★★
() автор топика

Вы можете точно указать, какие именно байты находятся в передаваемых данных на месте этой большой буквы И? И еще вопрос на засыпку - какая кодировка используется currentValue.getBytes() во второй строчке?

svu ★★★★★
()
Ответ на: комментарий от svu

byte[] java.lang.String.getBytes() Encodes this String into a sequence of bytes using the platform's default charset, storing the result into a new byte array. У меня default charset Cp1251, то есть однобайтовая кодировка.

На входе {-48, 63}, что странно, так как И в утф-8 - это D0 98.

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Bohtvaroh

В том-то и вопрос - откуда берутся -48, 63? Доп. вопрос - в самом http запросе что идет? Какие байтики? Я б попробовал банально перехватить запрос при помощи хотя бы ethereal. Опять же, распечатать currentValue было б интересно.

svu ★★★★★
()
Ответ на: комментарий от svu

Глянул вайршарком:

POST /fms-sou/docview_registrationcard/ajaxresponse.do HTTP/1.1
Accept: */*
Accept-Language: ru
x-prototype-version: 1.4.0
Referer: http://semenov:8080/fms-sou/docview_registrationcard/preparedocument.do
x-requested-with: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: semenov:8080
Content-Length: 64
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=98538F3CAC24A55E068C00B0B04847AA

guest.citizenShip=%D0%98&currentValue=%D0%98&mode=citizenShip&_
HTTP/1.1 200 OK

Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
Cache-Control: no-cache
Content-Type: text/xml;charset=UTF-8
Content-Length: 91
Date: Mon, 28 May 2007 14:38:32 GMT

<?xml version="1.0" encoding="UTF-8" ?><ajax-response><response></response></ajax-response>
;


А ведь и вправду уходит currentValue=%D0%98.

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Bohtvaroh

Уже в самой первой строке currentValue.getBytes() = {-48, 63}. Попробовал request.setCharacterEncoding("UTF-8"); - не помогло.

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от svu

> Что будет, если распечатать хекскоды currentValue.getBytes("UTF-8")?

[-48, -96, -17, -65, -67]

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Zmacs

> Помню, бага такая была в томкате. До сих пор не исправили шоле?

O_O

JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
                                                            ^^^^^^^^^^

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Bohtvaroh

Я спрашиваю, что будет, если currentValue.getBytes("UTF-8") - с параметром, явно задающим кодировку. PS Боюсь, придется настроить сервер на использование UTF...

svu ★★★★★
()
Ответ на: комментарий от svu

> А если явно указать CP1251? Похоже на багу в аппсервере...

То же самое. Выше говорят, что действительно бага, правда, погуглив, я её описание не нашёл. :-/

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Bohtvaroh

В общем решил проблему не самым красивым, но действенным способом. В экшене:

byte[] bytes = currentValue.getBytes();
if (bytes.length == 2 && bytes[0] == -48 && bytes[1] == 63) {
  bytes[0] = (byte) 208;
  bytes[1] = (byte) 152;
}

Bohtvaroh ★★★★
() автор топика

Жесть ребята.

eXOR ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.