站長www.software8.co

          熱轉(zhuǎn)印www.heatpress123.net

          那些年JavaWeb的各種中文亂碼終極解決方法?。?/a>

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

          posted on 2012-09-23 23:04 文哥哥 閱讀(1326) 評論(0)  編輯  收藏

          <2012年9月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆檔案

          文章檔案

          友情鏈接

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 留坝县| 师宗县| 尚志市| 英德市| 防城港市| 黔东| 铜鼓县| 济南市| 左贡县| 栾城县| 普定县| 镶黄旗| 瑞安市| 高要市| 花垣县| 易门县| 堆龙德庆县| 沁阳市| 上犹县| 乌兰察布市| 淮阳县| 宜兴市| 石家庄市| 嘉义市| 建始县| 临沭县| 芦溪县| 临泽县| 新邵县| 泾川县| 扎囊县| 临沭县| 南投县| 防城港市| 安义县| 建水县| 晋中市| 太康县| 南澳县| 会东县| 定西市|