2014-02-19 1 views
2

Я хочу отправить XML-сообщение на сервер из приложения Android Mobile через HTTP-сообщение.Кодирование проблемы с HttpUrlConnection в Android

Я пробовал с HttpURLConnection, выполнив следующие действия:

URL url = new URL(vURL); 

HttpUrlConnection conn = (HttpURLConnection) url.openConnection(); 

conn.setDoInput(true); 
conn.setDoOutput(true); 

// Adding headers (code removed) 

conn.setRequestProperty("Content-Type", "text/xml; charset=utf-16"); 
OutputStream out = new BufferedOutputStream(conn.getOutputStream()); 

// Adding XML message to the connection output stream 
// I have removed exception handling to improve readability for posting it here 
out.write(pReq.getBytes()); // here pReq is the XML message in String 
out.close(); 

conn.connect(); 

После того, как я получаю ответ, поток чтения часть в Делается это так:

BufferedReader in = null; 
StringBuffer sb; 
String result = null; 

    try { 

     InputStreamReader isr = new InputStreamReader(is); 
      // Just in case, I've also tried: 
      // new InputStreamReader(is, "UTF-16"); 
      // new InputStreamReader(is, "UTF-16LE"); 
      // new InputStreamReader(is, "UTF-16BE"); 
      // new InputStreamReader(is, "UTF-8"); 

     in = new BufferedReader(isr); 

     sb = new StringBuffer(""); 
     String line = ""; 

     while ((line = in.readLine()) != null) 
      sb.append(line); 

     in.close(); 

     result = sb.toString(); 

    } catch (Exception e) { 

     e.printStackTrace(); 
    } 

Теперь строка результата я get находится в некотором нечитаемом формате/кодировке.

Когда я пытаюсь сделать то же самое с HttpClient, он работает правильно. Вот потоковое чтение часть, как только я получаю HttpResponse после вызова HttpClient.execute:

BufferedReader in = null; 
    InputStream   is; 
    StringBuffer sb; 
    String decompbuff = null; 

    try { 

     is = pResponse.getEntity().getContent(); 
     InputStreamReader isr = new InputStreamReader(is); 
     in = new BufferedReader(isr); 

     // Prepare the String buffer 
     sb = new StringBuffer(""); 

     String line = ""; 

     while ((line = in.readLine()) != null) 
      sb.append(line); 

     in.close(); 

     // gZip decompression of response. Note: message was compressed before 
     // posting it via HttpClient (Posting code is not mentioned here) 
     decompbuff = Decompress(sb.toString()); 

    } catch (Exception e) { 

     e.printStackTrace(); 
    } 

    return decompbuff; 

Некоторая помощь ценится в понимании проблемы.

+1

Можете ли вы показать нам свой 'writestream (out);' реализация? Вы закрываете поток? У вас действительно есть UTF16? Маленький или Большой-Эндиан? С/без спецификации? Как выглядит ответ? Можете ли вы показать нам код, который работает с HttpClient? – hgoebl

+0

В ответ на ваши вопросы: Я закрываю поток после его написания. Я отправлю код, который работает с HttpClient за несколько минут. Ответ, который я получаю в строке результата, выглядит как «китайские символы» :). Я не понял, о чем вы говорите, - «У вас действительно есть UTF 16 ...» – sg1

ответ

1

Одна (серьезная) проблема может заключаться в том, что вы игнорируете кодирование ввода и вывода.

Входной

conn.setRequestProperty("Content-Type", "text/xml; charset=utf-16"); 
OutputStream out = new BufferedOutputStream(conn.getOutputStream()); 

// Adding XML message to the connection output stream 
// I have removed exception handling to improve readability for posting it here 
out.write(pReq.getBytes()); // <-- you use standard platform encoding 
out.close(); 

лучше:

out.write(pReq.getBytes("UTF-16")); 

Выход

Вы, вероятно, игнорировали сжатие, что будет лучше выглядеть следующим образом (взяты из DavidWebb):

static InputStream wrapStream(String contentEncoding, InputStream inputStream) 
     throws IOException { 
    if (contentEncoding == null || "identity".equalsIgnoreCase(contentEncoding)) { 
     return inputStream; 
    } 
    if ("gzip".equalsIgnoreCase(contentEncoding)) { 
     return new GZIPInputStream(inputStream); 
    } 
    if ("deflate".equalsIgnoreCase(contentEncoding)) { 
     return new InflaterInputStream(inputStream, new Inflater(false), 512); 
    } 
    throw new RuntimeException("unsupported content-encoding: " + contentEncoding); 
} 

// ... 

    InputStream is = wrapStream(conn.getContentEncoding(), is); 
    InputStreamReader isr = new InputStreamReader(is, "UTF-16"); 

    in = new BufferedReader(isr); 

    sb = new StringBuffer(""); 
    String line = ""; 

    while ((line = in.readLine()) != null) 
     sb.append(line); // <-- you're swallowing linefeeds! 

    in.close(); 
    result = sb.toString(); 

Было бы лучше, если бы XML-Parser потреблял ваш InputStream напрямую. Не создавайте строку JAVA, но пусть анализатор сканирует байты. Он автоматически определит кодировку XML.

Как правило, может быть проблема, потому что мы не знаем, какой тип UTF-16 вы используете. Может быть BigEndian или LittleEndian. Вот почему я спросил, действительно ли вам нужен UTF-16. Если вам не нужно заниматься некоторыми азиатскими языками, UTF-8 должен быть более эффективным и простым в использовании.

Таким образом, «решение», которое я вам дал, не гарантированно работает - вам нужно немного поиграть с UTF-16 BE/LE, и я желаю вам удачи и терпения.

Другое замечание: в приведенном выше примере вы сначала построили строку, а затем Decompress. Это неправильный порядок. Поток сжат (gzip, deflate) и должен быть сначала распакован. Затем вы получите строку.

Смежные вопросы