使用HttpURLConnection发送UTF-8字符串

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

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

 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 String的编码工作)。

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

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

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

如果调用close()flush()也是可选的。

peter.petrov提到的另一个选项是首先将String转换为字节(在内存中),然后将字节数组输出到输出流。

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

StringEntity使用Charset来确保编码是正确的。 它确实〜:

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

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

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

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

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