使用HttpURLConnection发送UTF-8字符串

时间:2014-06-05 12:54:36

标签: java android json httpurlconnection

到目前为止,我已使用以下代码段来发送和接收JSON字符串:

static private String sendJson(String json,String url){
    HttpClient httpClient = new DefaultHttpClient();
    String responseString = "";
    try {
        HttpPost request = new HttpPost(url);
        StringEntity params =new StringEntity(json, "UTF-8");
        request.addHeader("content-type", "application/json");
        request.setEntity(params);
        HttpResponse response = httpClient.execute(request);
        HttpEntity entity = response.getEntity();
        responseString = EntityUtils.toString(entity, "UTF-8");

    }catch (Exception ex) {
        ex.printStackTrace();
        // handle exception here
    } finally {
        httpClient.getConnectionManager().shutdown();
    }
    return responseString;
}

上面的代码工作得很好,即使json字符串包含UTF-8字符,一切正常。

由于多种原因,我不得不改变发送HTTP post请求的方式,并使用HttpURLConnection代替apache的HttpClient。这是我的代码:

static private String sendJson(String json,String url){
    String responseString = "";
    try {
        URL m_url = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)m_url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("content-type", "application/json");
        DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
        outputStream.writeBytes(json);
        outputStream.flush();
        outputStream.close();

        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line+"\n");
        }
        br.close();
        responseString = sb.toString();
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return responseString;
}

此代码适用于普通英文字符,但似乎不支持json字符串中的UTF-8字符,因为它每次都会失败。 (当发送json到服务器时,服务器压缩说utf8无法解码某个字节,但是当从服务器接收utf8 json时我认为它确实有效,因为我设法查看特殊字符)。

服务器根本没有变化,并且在之前的代码中工作正常,因此这个新代码片段的问题是100%。

任何想法如何修复json字符串发送所以它将支持UTF 8?谢谢

3 个答案:

答案 0 :(得分:29)

我认为问题在于这一部分:

DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
outputStream.writeBytes(json);
outputStream.flush();
outputStream.close();

您需要将json编码为UTF-8,而不是这样做 并发送表示UTF-8编码的字节。

尝试使用:

Charset.forName("UTF-8").encode(json)

请参阅:

Charset.encode

更简单的方法是使用例如一个BufferedWriter包裹着 OutputStreamWriterOutputStreamWriter知道自己的编码 因此它将为您完成工作(json字符串的编码工作)。

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
bw.write(json);
bw.flush();
bw.close();

答案 1 :(得分:4)

String写入输出流(字节)时,需要指定进行转换的编码。 一种方法是将输出流包装在OutputStreamWriter中,该 conn.setRequestProperty("content-type", "application/json; charset=utf-8"); Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); writer.write(json); writer.close(); 将使用UTF-8字符集进行编码。

flush()

如果您致电close()String也是可选的。

peter.petrov提到的另一个选项是首先将"content-type", "application/json; charset=utf-8"转换为字节(在内存中),然后将字节数组输出到输出流。

为了在服务器端显而易见,您可以传递内容类型标头({{1}})中使用的字符集。

答案 2 :(得分:1)

StringEntity使用Charset来确保编码正确。确实如此:

byte[] content = s.getBytes(charset);

您的代码没有太大变化,您的写作可以是:

outputStream.write(json.getBytes("UTF-8"));

至于您的阅读,使用BufferedReaderreadLine没有任何意义,除了规范化行尾。它比其他方法慢得多,因为它需要单独读取每个字节。

EntityUtils主要是这样做的:

    Reader reader = new InputStreamReader(conn.getInputStream(), "UTF-8");
    StringBuilder buffer = new StringBuilder();
    char[] tmp = new char[1024];
    int l;
    while((l = reader.read(tmp)) != -1) {
        buffer.append(tmp, 0, l);
    }
    responseString = buffer.toString();