一、Servlet輸出亂碼
1. 用servlet.getOutStream字節(jié)流輸出中文,假設要輸出的是String str ="釣魚島是中國的,無恥才是日本的"。
1.1 若是本地服務器與本地客戶端這種就不用說了,直接可以out.write(str.getBytes())可以輸出沒有問題。因為服務器中用str.getBytes()是采用默認本地的編碼,比如GBK。而瀏覽器也解析時也用本地默認編碼,兩者是統(tǒng)一的,所以沒有問題。
1.1 若服務器輸出時用了, out.write(str.getBytes("utf-8"))。而本地默認編碼是GBK時(比例在中國),那么用瀏覽器打開時就會亂碼。因為服務器發(fā)送過來的是utf-8的1010數(shù)據(jù),而客戶端瀏覽器用了gbk來解碼,兩者編碼不統(tǒng)一,肯定是亂碼。當然,你也可以自己將客戶端瀏覽器的編碼手工調用下(IE菜單是:查詢View->編碼encoding->utf-8),但是這種操作很爛,最好由服務器輸出響應頭告訴,瀏覽器用哪種編碼來解碼。所以要在服務器的servlet中,增加response.setHeader("content-type","text/html;charset=utf-8"),當然也可直接用簡單的response.setContentType("text/hmtl;charset=utf-8")。兩種的操作是一樣一樣的。
2. 用servlet.getWirter字符流輸出中文,假設要輸出的是String str ="釣魚島是中國的,無恥才是日本的"。
2.1 若寫成out.print(str)輸出時,客戶端瀏覽器顯示的將全是多個?????的字符,代表在編碼表中肯定就找不到相應的字符來顯示。原因是:servlet.getWriter()得到的字符輸出流,默認對字符的輸出是采用ISO-8859-1,而ISO-8859-1肯定是不支持中文的。所以肯定要首先要做的第一件事:是要將服務器對象輸出字符能支持中文的。其次服務器向客戶端寫回的響應頭要告訴客戶端是用了哪種編碼表進行編碼的。而實現(xiàn)這兩個需求,只需要response.setContentType("text/hmtl;charset=utf-8")。就搞定了。特別注意:response.setContentType("text/html;charset=utf-8")要放在PrintOut out = response.getWriter()代碼的前面,否則只是有告訴客戶端用什么碼表編碼的功能,而服務器端還是用ISO-8859-1編碼了。再特別提示下:在同一Servlet中的doGet或doPost方法中,不能既用response.getOutputStream又用response.getWriter,因為這兩種response的響應輸出字節(jié)流與字符流是沖突的,只能用其一。
二、Servlet文件下載,中文亂碼情況。
關鍵是下載時響應頭 content-disposition中attachment;filename=文件名。這個文件名filename不能是含有中文字符串的,要用URLEncoding編碼進行編碼,才能進行進行http的傳輸。如下代碼示例:
[java] view plaincopy
//獲取文件的URL地址
String realPath = getServletContext().getRealPath("/釣魚島是中國的無恥才是日本的歷史證據(jù).jpg");
//獲取文件名: 釣魚島是中國的無恥才是日本的歷史證據(jù).jpg
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//指示響應流的類型不是text/html而是二進制流數(shù)據(jù)以指示下載
response.setContentType("application/octet-stream");
//注意這里一般都用URLEncoder的encode方法進行對文件名進行編碼
String enFileName = URLEncoder.encode(fileName, "utf-8");
//enFileName文件名若含有中文必須用URLEncoding進行編碼
response.setHeader("content-disposition", "attachment;filename="+enFileName);
//文件讀取與輸出,模板代碼了...
InputStream in = new FileInputStream(realPath);
OutputStream out = response.getOutputStream();
int len = -1;
byte[] buf = new byte[1024];
while((len=in.read(buf))!=-1){
out.write(buf, 0, len);
}
in.close();
三、Servlet的response增加addCookie,cookie中value的中文碼問題解決方法。
關于cookie的原理,見http://blog.csdn.net/chenshufei2/article/details/8009992。 若想將cookie中存放中文的值,必須用Base64編碼后,發(fā)給客戶瀏覽器端進入存儲。而下次客戶端瀏覽訪問是帶回來的cookie中的值,是經(jīng)過Base64編碼的,所以需要用Base64解碼即可。 Base64編碼主要是解決將特殊字符進行重新編碼,編碼成a-b、A-B、0-9、+與/,字符52,10個數(shù)字與一個+,一個/ 共64個字符。它的原理是將原來3個字節(jié)的內(nèi)容編碼成4個字節(jié)。主要是取字節(jié)的6位后,在前面補00組成一個新的字節(jié)。所以這樣原來的3個字節(jié)共24,被編碼成4個字節(jié)32位了。
具體代碼示例如下:
[java] view plaincopy
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
String getUserName = request.getParameter("username");
PrintWriter out = response.getWriter();
String username = null;
//獲取客戶端提交過來的cookie數(shù)組。
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
//遍歷cookie數(shù)組,找到含有username的key的cookie。
if (Constant.USER_INFO.equals(cookies[i].getName())) {
username = cookies[i].getValue();
//得到cookie的值后必須,進行Base64解碼,因為前次生成cookie時,value是經(jīng)過Base64編碼。
username = Base64Coder.decode(username); //進行Base64解碼
}
}
out.print(username + ",恭喜您登錄成功......"+getUserName); //username從Cookie中得出來,getUserName從請求參數(shù)中
System.out.println(username+"------------");
String remember = request.getParameter("remember");
//中文必須要進行 base64進行加碼,才能作為cookie的值
getUserName = Base64Coder.encode(getUserName);
//將編碼后的中文username的作為cookie的value
Cookie cookie = new Cookie(Constant.USER_INFO, getUserName);
cookie.setPath(getServletContext().getContextPath());
if(null != remember){ //若選擇中了,則將Cookie寫進去,若沒有選擇中,則將以前的Cookie都置成空
cookie.setMaxAge(Integer.MAX_VALUE); //設置Cookie是Integer最大數(shù),好似有70多年的存效吧。呵呵
}else{
cookie.setMaxAge(0); //設置成cookie馬上失效,maxAge是cookie的存活時間
}
response.addCookie(cookie);
四、獲取請求參數(shù)亂碼
GET方式的亂碼:
如
CN,直接用request.getParameter得到的字符串strCN將會亂碼,這也是因為GET方式是用http的url傳過來的默認用iso-8859-1編碼的,所以首先得到的strCn要再用iso-8859-1編碼得到原文后,再進行用utf-8(看具體頁面的charset是什么utf-8或gbk)進行解碼即可。new String(strCn.getBytes(“ISO-8859-1”),“UTF-8”);
[java] view plaincopy
String strCn = request.getParameter("name");
String name = new String(strCn.getBytes(“ISO-8859-1”),“UTF-8”);
這種方式操作比較麻煩的是,有一個參數(shù)要用iso-8859-1編碼一次再解碼一次。
POST方式的亂碼:只需要request.setCharacterEncoding("UTF-8"):即可。
[java] view plaincopy
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
個人小站 www.software8.co