2011-01-19 3 views
1

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

Содержание длины в этом случае 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(); 

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

EDIT: Я удалил заголовочное поле «content-lenght», и оно работает, но почему?

ответ

1

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

+0

спасибо, это разъяснение помогло. Я из C/C++ фона и никогда не понял, что java имеет 16-битный тип char :) –

0

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

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

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

Reference

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

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

+0

Я работаю с UTF-8, и переменная requestBody уже закодирована. И упоминание кодировки при создании выходного потока тоже не помогает (отредактировано в исходном сообщении). –

3

Этот код устанавливает свойство 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); 
Смежные вопросы