HttpClient傳送請求後得到的響應內容出現部分亂碼的問題
這幾天爬蟲出現了一個問題,用HttpClient不管是傳送的Post請求還是Get請求一直出現一個問題:得到的響應內容部分亂碼,請注意我的措辭,是部分亂碼,一小部分,一小部分,一小部分!!!
出問題的程式碼在這裡:
package com.springapp.parse;
import org.apache.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* Created by BearSmall on 2015/10/26.
* 響應工具類
*/
public class ResponseUtils {
/**
* 返回響應正文(有亂碼)
* @param response
* @return
*/
public static String getResponseString(HttpResponse response) throws IOException {
HttpEntity entity = response.getEntity();//響應實體類
StringBuilder result = new StringBuilder();//響應正文
if (entity != null) {
String charset = getContentCharSet(entity);
InputStream instream = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(
instream));
String temp = "";
while ((temp = br.readLine()) != null ) {
String str = new String(temp.getBytes(), "UTF-8");
result.append(str+"\n");
}
}
return result.toString();
}
}
發現這段程式碼出現了亂碼問題,已知的情況是:響應的正文是utf-8格式的。出問題的地方也是這個位子。由於對java編碼解碼理解得不是太透徹,試過很多笨辦法,果然解決了部分亂碼問題,但是來了個全部亂碼。。。。。。。果然是個冷笑話。本來打算就這樣了,反正影響不是特別大,但是越往後面這個問題越來越明顯。基本上爬下來的大一點的頁面都會零零散散的出現亂碼現象,很是討人嫌。
最後發現了問題的癥結所在,這裡跟大家分享一下:
從程式碼上看,沒有邏輯上的錯誤。我們就看看細節吧。
首先從響應物件response中得到InputStream 流。然後包裝成BufferredReader物件。最後一行一行的讀取。但是這樣讀取的字串會出現亂碼,於是我們從新對讀到的每一行字串重新編碼,設定成和inputstream匹配的utf-8。大面積亂碼確實不見了,但是卻出現小面積的亂碼。。。。。。
我們再仔細想一想,我們已經知道inputStream的編碼格式為utf-8,那為什麼要在最後字串都一行行讀取出來了的情況下將其轉化呢?難道不能用另外的方式實現處理這個utf-8,讓讀出來的一行行的字串就不存在亂碼,這樣就省得我們一行行的去重新編碼。
果然,看過InputStreamReader的建構函式後,我們發現它有一個兩個引數的建構函式,另一個引數就是用來指定字符集的。於是我們果斷用上。
package com.springapp.parse;
import org.apache.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* Created by BearSmall on 2015/10/26.
* 響應工具類
*/
public class ResponseUtils {
/**
* 返回響應正文(無亂碼)
* @param response
* @return
*/
public static String getResponseString(HttpResponse response) throws IOException {
HttpEntity entity = response.getEntity();//響應實體類
StringBuilder result = new StringBuilder();//響應正文
if (entity != null) {
String charset = getContentCharSet(entity);
InputStream instream = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(
instream,"utf-8"));
String temp = "";
while ((temp = br.readLine()) != null) {
result.append(temp+"\n");
}
}
return result.toString();
}
}
另外還有其他的做法:
package com.springapp.parse;
import org.apache.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* Created by BearSmall on 2015/10/26.
* 響應工具類
*/
public class ResponseUtils {
/**
* 返回響應正文(無亂碼)
* @param response
* @return
*/
public static String getResponseString(HttpResponse response) throws IOException {
HttpEntity entity = response.getEntity();//響應實體類
StringBuilder result = new StringBuilder();//響應正文
if (entity != null) {
InputStream instream = entity.getContent();
byte[] bytes = new byte[4096];
int size = 0;
try {
while ((size = instream.read(bytes)) > 0) {
String str = new String(bytes, 0, size, "utf-8");
result.append(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result.toString();
}
這裡由於沒有使用包裝類,所以需要自己編碼解碼。但是這裡和第一個那種出現亂碼的方式還是有區別的,雖然都是自己編碼解碼,但是這裡是對純的inputStream進行的操作,中間不涉及包裝類的額外編碼附操作。