【问题标题】:Encoding Issue with HttpUrlConnection in AndroidAndroid 中 HttpUrlConnection 的编码问题
【发布时间】:2014-02-19 09:31:00
【问题描述】:

我想通过 HTTP post 从我的 Android 移动应用程序向服务器发送 XML 消息。

我使用 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();
    }

现在我得到的结果字符串是某种不可读的格式/编码。

当我使用 HttpClient 尝试相同的操作时,它可以正常工作。这是在 HttpClient.execute 调用后获得 HttpResponse 后的流式读取部分:

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;

感谢您对理解问题的帮助。

【问题讨论】:

  • 您能向我们展示您的writestream (out); 实现吗?你要关闭流吗?你真的有UTF16吗?小端还是大端?有/没有 BOM?响应如何?你能告诉我们使用 HttpClient 的代码吗?
  • 回答您的问题:我在写入后关闭流。我将在几分钟后发布与 HttpClient 一起使用的代码。我在“结果”字符串中得到的响应看起来像“中文字符”:)。我不明白你的意思 - “你真的有 UTF 16 ...”

标签: android encoding httpclient httpurlconnection


【解决方案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),必须先解压缩。然后你得到字符串。

【讨论】:

    猜你喜欢
    • 2018-04-23
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多