今天遇到了一个小问题,简单研究了一下,同时记录一下。
关于apache的HttpGet\HttpPost请求,做了一次访问,代码如下:
String url = "http://xxxxxxx";
HttpGet httpGet = new HttpGet(url);
HttpClient httpClient = new DefaultHttpClient();
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
//String result = EntityUtils.toString(httpEntity, "utf-8");
InputStream is = null;
is = httpEntity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String result = "";
String line = "";
while ((line = reader.readLine()) != null) {
result = result + line;
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
结果出现了乱码。立刻对代码进行修改BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
依旧出现乱码,到底是哪里出问题?
如果用第7行的方式来获取的话就不会有乱码。
第7行的方法很简单,深入研究下实际上也是获取流进行处理,只是在过程中加入了编码处理,那么到底是怎么处理的?
该方法源码如下:
public static String toString(
final HttpEntity entity, final String defaultCharset) throws IOException, ParseException {
if (entity == null) {
throw new IllegalArgumentException("HTTP entity may not be null");
}
InputStream instream = entity.getContent();
if (instream == null) {
return "";
}
if (entity.getContentLength() > Integer.MAX_VALUE) {
throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
}
int i = (int)entity.getContentLength();
if (i < 0) {
i = 4096;
}
String charset = getContentCharSet(entity);
if (charset == null) {
charset = defaultCharset;
}
if (charset == null) {
charset = HTTP.DEFAULT_CONTENT_CHARSET;
}
Reader reader = new InputStreamReader(instream, charset);
CharArrayBuffer buffer = new CharArrayBuffer(i);
try {
char[] tmp = new char[1024];
int l;
while((l = reader.read(tmp)) != -1) {
buffer.append(tmp, 0, l);
}
} finally {
reader.close();
}
return buffer.toString();
}
可以看见是在InputStreamReader这里处理的。和我处理的地方是一致的,那么还有什么问题?
后来仔细一看发现toString()方法传入的编码方式未必就是最后使用的,这中间还有个判断,就是判断HttpEntity返回的header是否存在charset,不存在才会使用传入的参数。
本来我一直认为这个参数就应该是utf-8,结果用EntityUtils的getContentCharSet方法一获取才发现是GBK。。。
这下就清楚了,修改代码BufferedReader reader = new BufferedReader(new InputStreamReader(is, "gbk"));
这回不是乱码了,不过这部分应该在前面做好判断,先用getContentCharSet获取一下,如果是空再自己设定一个才好。
至于getContentCharSet方法如何实现的,代码如下:
public static String getContentCharSet(final HttpEntity entity)
throws ParseException {
if (entity == null) {
throw new IllegalArgumentException("HTTP entity may not be null");
}
String charset = null;
if (entity.getContentType() != null) {
HeaderElement values[] = entity.getContentType().getElements();
if (values.length > 0) {
NameValuePair param = values[0].getParameterByName("charset");
if (param != null) {
charset = param.getValue();
}
}
}
return charset;
}