Метод сброса OutputStreamWriter выдает IOException при попытке написать китайские символы - PullRequest
1 голос
/ 19 января 2011

Ниже приведен код, который я использую для отправки запросов SOAP в моем приложении Android, и он отлично работает со всеми запросами, кроме одного.Этот код выдает IOException: длина содержимого превысила на wr.flush();, когда в переменной requestBody есть китайские символы.

Длина содержимого в этом случае 409

            URL url = new URL(Constants.HOST_NAME);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // Modify connection settings
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            connection.setRequestProperty("SOAPAction", soapAction);

            String requestBody = new String(soapRequest.getBytes(),"UTF-8");
            int lngth = requestBody.length();
            connection.setRequestProperty("Content-Length", (""+lngth));

            // Enable reading and writing through this connection
            connection.setDoInput(true);
            connection.setDoOutput(true);

            // Connect to server
            connection.connect();

            OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            wr.write(requestBody);
            wr.flush();
            wr.close();

Любая подсказка, что происходит, когда в строке есть китайские символы?

РЕДАКТИРОВАТЬ: Я удалил поле заголовка 'content-lenght', и оно работает, но почему?

Ответы [ 3 ]

3 голосов
/ 19 января 2011

Этот код устанавливает свойство Content-Length запроса равным количеству символов в строковом представлении сообщения:

String requestBody = new String(soapRequest.getBytes(),"UTF-8");
int lngth = requestBody.length();
connection.setRequestProperty("Content-Length", (""+lngth));

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

OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

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

byte[] message = soapRequest.getBytes();
int lngth = message.length;
connection.setRequestProperty("Content-Length", (""+lngth));

// ...

connection.getOutputStream().write(message);
1 голос
/ 21 января 2011

Для упрощения другого ответа: длина содержимого ДОЛЖНА быть длиной в байтах, а вы указываете длину в символах (16-разрядный тип символов Java). Это разные, в общем. Поскольку UTF-8 является кодированием с переменной длиной байта, существует разница для всего, что выходит за пределы базового 7-битного диапазона ASCII. Другой ответ показывает правильный способ написания кода.

0 голосов
/ 19 января 2011

Я предполагаю, что вы не конвертировали китайцев в utf-8. Если вы поддерживаете пользователей, которые вводят двойные и расширенные наборы символов в свои поля, вам необходимо убедиться, что ваши входные данные из этих наборов символов (ASCII, UNICODE или UCS) преобразованы в UTF-8.

Определив кодировки символов, с которыми вы работаете, вы можете использовать что-то вроде:

FileInputStream(inputFile), "inputencoding");
Writer output = new OutputStreamWriter(new FileOutputStream(outputFile), "outputencoding");

Ссылка

при создании потоков для чтения / записи для преобразования между двумя.

Другая альтернатива заключается в настройке свойства запроса, управляющего языком http-запроса. Я не знаю много об этом.

...