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流是字符流,只能處理字符數據,如果用字符流處理字節數據,會導致數據丟失。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM