到目前为止,我使用以下代码片段来发送和接收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个字符,上面的代码也能很好地工作,一切都很好。
出于几个原因,我不得不改变发送HTTPpost请求的方式,并使用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字符串发送,以便支持UTF8吗?谢谢
我认为问题出在这一部分:
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
包装OutputStreamWriter
。OutputStreamWriter
知道自己的编码
,因此它会为您完成工作(json
String的编码工作)。
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
bw.write(json);
bw.flush();
bw.close();
将String
写入输出流(字节)时,需要指定进行转换的编码。一种方法是将输出流包装在将使用UTF字符集进行编码的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();
如果您调用close()
,flush()
也是可选的。
Peter. petrov提到的另一种选择是首先将您的String
转换为字节(在内存中),然后将字节数组输出到您的输出流。
为了在服务器端显而易见,您可以传递内容类型标头中使用的字符集("content-type","application/json; charset=utf-8"
)。
StringEntity
使用Charset
来确保编码正确。它确实~that:
byte[] content = s.getBytes(charset);
在代码没有太大变化的情况下,您的编写可以:
outputStream.write(json.getBytes("UTF-8"));
至于你的读取,除了规范行尾之外,将BufferedReader
与readLine
一起使用是没有意义的。它比其他方法慢得多,因为它需要单独读取每个字节。
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();