JavaEE中用response向客戶端輸出中文數(shù)據(jù)亂碼問題分析
Web服務(wù)器收到客戶端的http請求,會針對每一次請求,分別創(chuàng)建一個用于代表請求的request對象,和代表響應(yīng)的response對象。request和response對象既然代表請求和響應(yīng),那我們要獲取客戶機提交過來的數(shù)據(jù),只需要找request對象就行了。要向客戶機輸出數(shù)據(jù),只需要找response對象就行了。
package com.yyz.response;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//輸出中文的問題
public class ResponseDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "中國";
OutputStream out = response.getOutputStream();
out.write(data.getBytes());
/**
* out.write(data.getBytes());這句代碼涉及兩次查閱碼表。
* "中國"從字符數(shù)據(jù)變成字節(jié)數(shù)據(jù)的時候,會查閱gb2312碼表。
* 數(shù)據(jù)發(fā)送到瀏覽器端要顯示的時候,需要再次查閱碼表,這時查閱的碼表與瀏覽器的設(shè)置有關(guān)。
*/
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
瀏覽器編碼設(shè)置為GB2312時的測試結(jié)果:
瀏覽器編碼設(shè)置為UTF-8時的測試結(jié)果:
為了讓我們的網(wǎng)站能被國外用戶訪問,我們在將字符數(shù)據(jù)變成字節(jié)數(shù)據(jù)時,要指定轉(zhuǎn)換的碼表為UTF-8。但這時如果瀏覽器以GB2312打開,又會出現(xiàn)亂碼問題。雖然可以通過改變?yōu)g覽器的設(shè)置來解決這個亂碼問題,但不利于增強用戶體驗。因而我們需要用程序告訴瀏覽器查閱何種碼表顯示數(shù)據(jù)。
package com.yyz.response;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//輸出中文的問題
public class ResponseDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//在服務(wù)器端,數(shù)據(jù)是以哪個碼表輸出的,那么就要控制瀏覽器以哪個碼表打開。
String data = "中國";
response.setHeader("content-type", "text/html;charset=UTF-8");
OutputStream out = response.getOutputStream();
out.write(data.getBytes("UTF-8"));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
多學(xué)一招:
使用HTML語言里面的<meta>標簽來控制瀏覽器行為。
<meta http-equiv="Content-type'' content=''text/html;charset=UTF-8">
http-equiv模擬了HTTP的響應(yīng)頭,告訴瀏覽器以UTF-8的碼表打開。真正的響應(yīng)頭優(yōu)先于用http-equiv模擬的響應(yīng)頭。
實際開發(fā)中,服務(wù)器向瀏覽器寫文本數(shù)據(jù)應(yīng)該用字符流。但是通過response的getWriter方法拿到的字符流默認的碼表是ISO8859-1,這張碼表里是沒有中文對應(yīng)的編碼的,因而會把?對應(yīng)的編碼發(fā)送給瀏覽器,瀏覽器打開后全是問號。通過response的setCharacterEncoding可以修改服務(wù)端發(fā)送數(shù)據(jù)時查閱的碼表。
package com.yyz.response;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//輸出中文的問題
public class ResponseDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//在服務(wù)器端,數(shù)據(jù)是以哪個碼表輸出的,那么就要控制瀏覽器以哪個碼表打開。
String data = "中國";
response.setHeader("content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.write(data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
這里有幾個小細節(jié)需要注意:
1. response.setCharacterEncoding("UTF-8");需要寫在PrintWriter out = response.getWriter();的前面。拿到字符流后再設(shè)置編碼是沒有用的。
2. response.setHeader("content-type", "text/html;charset=UTF-8");有一種更為簡單的寫法response.setContentType("text/html;charset=UTF-8");。
3.response.setContentType("text/html;charset=UTF-8");這句代碼其實有兩個作用:通知response以UTF-8輸出和瀏覽器以UTF-8打開。即等價于response.setHeader("content-type", "text/html;charset=UTF-8");和response.setCharacterEncoding("UTF-8");兩句代碼。
4.通過以上閱讀,讀者應(yīng)該能明白為什么response.getOutputStream.write(1);這句代碼在瀏覽器的輸出不是1。因為瀏覽器是一個文本編輯器,收到數(shù)據(jù)后會拿著1去查碼表,然后顯示對應(yīng)字符。想在瀏覽器輸出數(shù)字,應(yīng)該把數(shù)字變成字符串,response.getOutputStream.write((1+"").getBytes());.
用OutputStream(字節(jié)流)發(fā)送數(shù)據(jù):
1、response.getOutputStream().write(“中國”.getBytes());//以默認編碼發(fā)送數(shù)據(jù)
2、response.getOutputStream().write("中國".getBytes("UTF-8"));//以UTF-8編碼發(fā)送數(shù)據(jù),瀏覽器(默認用GB2312)會出現(xiàn)亂碼
解決辦法:
2.1通過更改瀏覽器的編碼方式:IE/”查看”/”編碼”/”UTF-8”(不可取)
2.2通過設(shè)置響應(yīng)頭告知客戶端編碼方式:response.setHeader(“Content-type”, “text/html;charset=UTF-8”);//告知瀏覽器數(shù)據(jù)類型及編碼
2.3通過meta標簽?zāi)M請求頭:out.write("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />".getBytes());
2.4通過以下方法:response.setContentType("text/html;charset=UTF-8");
相關(guān)文章
一文帶你學(xué)會Java網(wǎng)絡(luò)編程
網(wǎng)絡(luò)編程是指編寫運行在多個設(shè)備(計算機)的程序,這些設(shè)備都通過網(wǎng)絡(luò)連接起來。這篇文章將帶大家深入了解一下Java的網(wǎng)絡(luò)編程,需要的可以了解一下2022-08-08解析WeakHashMap與HashMap的區(qū)別詳解
本篇文章是對WeakHashMap與HashMap的區(qū)別進行了詳細的分析介紹,需要的朋友參考下2013-05-05Spring?Boot教程之提高開發(fā)效率必備工具lombok
這篇文章主要介紹了Spring?Boot教程之提高開發(fā)效率必備工具lombok的相關(guān)資料,需要的朋友可以參考下2022-08-08idea使用easyCode生成代碼(根據(jù)mybatis-plus模板創(chuàng)建自己的模板)
本文主要介紹了idea使用easyCode生成代碼,easyCode代碼生成器可以減少低價值搬磚,具有一定的參考價值,感興趣的可以了解一下2023-10-10