Java 使用 HttpURLConnection 发送 UTF-8 字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24060787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:57:27  来源:igfitidea点击:

Sending UTF-8 string using HttpURLConnection

javaandroidjsonhttpurlconnection

提问by Jjang

till now I've used the following code snippet in order to send and recieve JSON strings:

到目前为止,我已经使用以下代码片段来发送和接收 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;
}

The code above worked perfect even if the json string contained UTF-8 chars, and everything worked fine.

即使 json 字符串包含 UTF-8 字符,上面的代码也能正常工作,并且一切正常。

For several reasons I had to change the way I send HTTP post requests and use HttpURLConnection instead apache's HttpClient. Here's my code:

出于多种原因,我不得不改变发送 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;
}

This code works well for normal English characters, but doesn't seem to support UTF-8 characters in the json string, since it fails each time. (when sending json to server, server crushes saying that utf8 cant decode a certain byte, but when recieving utf8 json from server I think it does work since I manage to view the special characters).

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

Server didn't change at all and worked fine with previous code, so the problem is 100% on this new code snippet.

服务器根本没有改变并且与以前的代码一起工作得很好,所以这个新代码片段的问题是 100%。

Any idea how to fix the json string sending so it would support UTF 8? Thanks

知道如何修复 json 字符串发送以支持 UTF 8 吗?谢谢

采纳答案by peter.petrov

I think the problem is in this part:

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

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

Instead of doing this you need to encode json as UTF-8
and send those bytes which represent the UTF-8 encoding.

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

Try using this:

尝试使用这个:

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

See:

看:

Charset.encode

字符集编码

An even simpler approach is to use e.g. a BufferedWriterwrapping an
OutputStreamWriter. The OutputStreamWriterknows about its own encoding
and so it will do the work for you (the encoding work of the jsonString).

一种更简单的方法是使用例如BufferedWriter包装一个
OutputStreamWriter. TheOutputStreamWriter知道它自己的编码
,因此它将为您完成工作(jsonString的编码工作)。

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

回答by Fradenger

When writing a Stringto an output stream (bytes), you need to specify the encoding to do the conversion. One way to do is to wrap the output stream in a OutputStreamWriterthat will use UTF-8 charset for the encoding.

将 a 写入String输出流(字节)时,您需要指定编码以进行转换。一种方法是将输出流包装在OutputStreamWriter将使用 UTF-8 字符集进行编码的 a 中。

        conn.setRequestProperty("content-type", "application/json;  charset=utf-8");
        Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
        writer.write(json);
        writer.close();

The flush()is also optional if you call close().

flush(),如果你打电话也是可选的close()

Another option, as mentionned by peter.petrovis to first convert your Stringto bytes (in memory) and then output the byte array to your output stream.

另一种选择,正如peter.petrov所提到的,首先将您String的字节转换为字节(在内存中),然后将字节数组输出到您的输出流。

And to make it obvious on the server side, you can pass the charset used in the content-type header ("content-type", "application/json; charset=utf-8").

为了在服务器端显而易见,您可以传递在内容类型标头 ( "content-type", "application/json; charset=utf-8") 中使用的字符集。

回答by njzk2

StringEntityuses a Charsetto make sure the encoding is right. It does ~that:

StringEntity使用 aCharset来确保编码正确。它确实〜:

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

Without much change in your code, your write can be:

无需对代码进行太多更改,您的编写可以是:

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

As for your read, there is no point in using a BufferedReaderwith readLine, except for normalizing the end of line. It is much slower than other methods, as it requires to read each byte individually.

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

EntityUtilsdoes mostly that:

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();