zoukankan      html  css  js  c++  java
  • 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流是字符流,只能处理字符数据,如果用字符流处理字节数据,会导致数据丢失。

  • 相关阅读:
    (转) Nova是如何统计OpenStack资源
    (转) 一次批量重启引发的Neutron网络故障
    (转)理解Keystone的四种Token
    neutron 虚拟机网络问题调试
    转 Nova: 虚机的块设备总结 [Nova Instance Block Device]
    kvm 客户机系统的代码是如何运行的
    12 while循环
    11猜拳游戏
    10 if 嵌套
    09 if...elif..else语句
  • 原文地址:https://www.cnblogs.com/10158wsj/p/6769213.html
Copyright © 2011-2022 走看看