servlet研究學習總結--OutputStream和PrintWriter的區別
當用戶和瀏覽器其進行互動時,會給伺服器傳送http請求,Web伺服器收到客戶端的http請求,會針對每一次請求,分別建立一個用於代表請求的request物件、和代表響應的response物件。request和response物件即然代表請求和響應,那我們要獲取客戶機提交過來的資料,只需要找request物件就行了。要向客戶機輸出資料,只需要找response物件就行了。
最近在做一個oa的專案,有一個圖片下載的介面,通過總結對比,總結一下response.getWriter().和response.getOutputStream(),這兩個方法的區別!
首先看一下HttpServletResponse的API對著兩個物件的介紹:
不同的是response.getOutputStream()向瀏覽器輸出的是二進位制資料,是位元組流,可以處理任意型別的資料,而response.getWriter()輸出的是字元型資料,是字元流。
1、使用OutputStream流和PrintWriter流向客戶端瀏覽器輸出中文資料
在伺服器端,資料的輸出碼錶要和控制客戶端瀏覽器相應的碼錶一致,比如:outputStream.write("中文".getBytes("UTF-8"));使用OutputStream流向客戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出,此時就要控制客戶端瀏覽器以UTF-8的編碼開啟,否則顯示的時候就會出現中文亂碼。
在伺服器端如何控制客戶端瀏覽器以以UTF-8的編碼顯示資料呢?
可以通過設定響應頭控制瀏覽器的行為,例如:response.setHeader("content-type", "text/html;charset=UTF-8");通過設定響應頭控制瀏覽器以UTF-8的編碼顯示資料。
1.1使用OutputStream流向瀏覽器輸出中文
1 package controller; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class ServletDemo01 extends HttpServlet { 11 private static final long serialVersionUID = 1L; 12 13 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 14 this.doPost(request, response); 15 } 16 17 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 18 19 String str="使用OutputStream輸出中文:我心自在"; 20 //在伺服器設定響應頭,告訴瀏覽器以utf-8的編碼顯示資料,如果不寫會出現中文亂碼 21 response.setHeader("content-type", "text/html;charset=UTF-8"); 22 //獲取OutputStream輸出流 23 OutputStream os=response.getOutputStream(); 24 /** 25 * getBytes的作用是將字元轉化為位元組陣列,如果不帶引數,預設根據系統環境來進行轉化 26 * 這裡指定以utf-8的編碼進行轉換 27 */ 28 byte[]b=str.getBytes("utf-8"); 29 //想客戶端(瀏覽器)輸出資料 30 os.write(b); 31 } 32 }
瀏覽器中輸入:http://localhost:8080/servlet_study/ServletDemo01,執行結果如下:
開啟瀏覽器除錯工具,可以看到相關編碼資訊:
1.2使用PrintWriter流向瀏覽器輸出中文
1 package controller; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class ServletDemo02 extends HttpServlet { 11 private static final long serialVersionUID = 1L; 12 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 this.doPost(request, response); 14 } 15 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 16 String str="使用PrintWriter輸出中文:我心自在"; 17 //設定中文編碼格式 18 response.setCharacterEncoding("utf-8"); 19 //獲取流 20 PrintWriter pw=response.getWriter(); 21 //輸出 22 pw.write(str); 23 pw.close(); 24 } 25 26 }
瀏覽器中輸入:http://localhost:8080/servlet_study/ServletDemo02,執行結果如下:
這裡需要注意的是: 在獲取PrintWriter輸出流之前首先使用"response.setCharacterEncoding(charset)"設定字元以什麼樣的編碼輸出到瀏覽器,如:response.setCharacterEncoding("UTF-8");設定將字元以"UTF-8"編碼輸出到客戶端瀏覽器,然後再使用response.getWriter();獲取PrintWriter輸出流,這兩個步驟不能顛倒.如果顛倒,設定將無效,還是會出現中文亂碼!
通過比較可以看出,當需要向瀏覽器輸出字元資料時,使用PrintWriter比較方便,因為不需要將字元轉化為位元組這一步!
1、使用OutputStream流和PrintWriter流下載檔案
最近在做一個專案,涉及到檔案的下載,所以特意整理出來做個比較。
檔案下載,在實際開發中用到的很多,最近做的專案便是,檢視圖片的時候,點選圖片的時候進行圖片下載,這裡將這兩個下載檔案的區別做簡要比較。
檔案下載,運用的步驟比較固定,大致分為以下幾步:
1.獲取要下載的檔案的絕對路徑(注意是絕對路徑)
2.獲取要下載的檔名(獲取檔名要注意中文檔名的問題,需進行編碼)
3.設定content-disposition響應頭控制瀏覽器,告訴瀏覽器以下載的形式開啟檔案
4.獲取要下載的檔案輸入流
5.建立資料緩衝區
6.通過response物件獲取OutputStream流
7.將FileInputStream流寫入到buffer緩衝區
8.使用OutputStream將緩衝區的資料輸出到客戶端瀏覽器
2.1使用OutputStream流下載中文檔案
package controller; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo03 extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取檔案的下載絕對路徑 String downloadPath=this.getServletContext().getRealPath("/download/陽光海灘.jpg"); //獲取檔名 String fileName=downloadPath.substring(downloadPath.lastIndexOf("\\")+1); //設定響應頭,告訴瀏覽器以下載的方式打來檔案,設定中文編碼,如果不設定會出現亂碼 response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8")); //獲取檔案流 InputStream is=new FileInputStream(downloadPath); int len=0; byte[]b=new byte[1024]; OutputStream os=response.getOutputStream(); while((len=is.read(b))!=-1){ //將緩衝區資料輸出到瀏覽器 os.write(b,0,len); } is.close(); } }
瀏覽器中輸入:http://localhost:8080/servlet_study/ServletDemo03可以成功下載圖片並且可以順利開啟,
2.1使用PrintWriter流下載中文檔案
package controller; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo03 extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取檔案的下載絕對路徑 String downloadPath=this.getServletContext().getRealPath("/download/陽光海灘.jpg"); //獲取檔名 String fileName=downloadPath.substring(downloadPath.lastIndexOf("\\")+1); //設定響應頭,告訴瀏覽器以下載的方式打來檔案,設定中文編碼,如果不設定會出現亂碼 response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8")); //獲取檔案流 FileReader fr=new FileReader(downloadPath); int len=0; char[] b=new char[1024]; PrintWriter os=response.getWriter(); while((len=fr.read(b))!=-1){ //將緩衝區資料輸出到瀏覽器 os.write(b,0,len); } fr.close(); } }
瀏覽器中輸入:http://localhost:8080/servlet_study/ServletDemo03可以成功下載,但是開啟的過程中卻出現了一下情況:
這是什麼原因造成的呢?
PrintWriter流處理節資料,會導致資料丟失,因此在編寫下載檔案功能時,要使用OutputStream流,避免使用PrintWriter流,因為OutputStream流是位元組流,可以處理任意型別的資料,而PrintWriter流是字元流,只能處理字元資料,如果用字元流處理位元組資料,會導致資料丟失。