1. 程式人生 > >servlet研究學習總結--OutputStream和PrintWriter的區別

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流是字元流,只能處理字元資料,如果用字元流處理位元組資料,會導致資料丟失。

源地址:https://www.cnblogs.com/10158wsj/p/6769213.html