当用户和浏览器其进行交互时,会给服务器发送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流向浏览器输出中文

 package controller;

 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 ServletDemo01 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 str="使用OutputStream输出中文:我心自在";
//在服务器设置响应头,告诉浏览器以utf-8的编码显示数据,如果不写会出现中文乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
//获取OutputStream输出流
OutputStream os=response.getOutputStream();
/**
* getBytes的作用是将字符转化为字节数组,如果不带参数,默认根据系统环境来进行转化
* 这里指定以utf-8的编码进行转换
*/
byte[]b=str.getBytes("utf-8");
//想客户端(浏览器)输出数据
os.write(b);
}
}

浏览器中输入:http://localhost:8080/servlet_study/ServletDemo01,运行结果如下:

打开浏览器调试工具,可以看到相关编码信息:

1.2使用PrintWriter流向浏览器输出中文

 package controller;

 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 ServletDemo02 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 str="使用PrintWriter输出中文:我心自在";
//设置中文编码格式
response.setCharacterEncoding("utf-8");
//获取流
PrintWriter pw=response.getWriter();
//输出
pw.write(str);
pw.close();
} }

浏览器中输入: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流是字符流,只能处理字符数据,如果用字符流处理字节数据,会导致数据丢失。

servlet研究学习总结--OutputStream和PrintWriter的区别的更多相关文章

  1. Servlet的学习之Request请求对象(3)

    本篇接上一篇,将Servlet中的HttpServletRequest对象获取RequestDispatcher对象后能进行的[转发]forward功能和[包含]include功能介绍完. 首先来看R ...

  2. Servlet的学习之Response响应对象(1)

    在之前学习了Servlet中的主体结构,包括Servlet的生命周期方法,和非生命周期方法能获取的一些非常重要的对象如ServletConfig.ServletContext对象等,而从这篇开始我们将 ...

  3. Servlet的学习之Session(3)

    在上一篇<Servlet的学习之Session(2)>我们知道了Session能实现一个会话过程中保存数据或者多个会话中实现同一个Session的关键因素就是Cookie,只是Cookie ...

  4. Servlet的学习之Session(1)

    在学习完了Servlet中的Cookie技术后,我们再来学习另一个能保存会话数据的技术——Session. Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其 ...

  5. Servlet的学习之Cookie

    从本篇开始学习Servlet技术中的Cookie专题. 首先来了解什么是“会话”.会话是web技术中的一个术语,可以简单的理解为:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭 ...

  6. Servlet的学习之Response响应对象(3)

    本篇来说明响应对象HttpServletResponse对象的最后一点内容. 首先来看响应对象控制浏览器定时刷新,在我的web应用[myservlet]中创建Servlet,在该Servlet中设置响 ...

  7. Servlet的学习之Response响应对象(2)

    本篇接上一篇<Servlet的学习之Response响应对象(1)>,继续从HttpServletResponse响应对象来介绍其方法和功能. 使用setHeader方法结合HTTP协议的 ...

  8. Servlet的学习(三)

    本篇接上一篇<Servlet的学习(二)> ,主要讲诉如何使用MyEclipse来开发Servlet,和导入Servlet所需要的源代码. 现在我们来创建一个web应用,就叫[myserv ...

  9. servlet入门学习之API

    java servlet API学习网址: http://tomcat.apache.org/tomcat-7.0-doc/servletapi/ http://tomcat.apache.org/t ...

随机推荐

  1. 剑指offer_(4)

    重建二叉树: 题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍 ...

  2. VueJs学习路线

    对于这个东西,我本人也是初学者,收集一些学习资源的链接,用于个人资源的学习,也分享给大家 lavyun的博客 里面有一些给初学者的建议,学习路线 http://www.cnblogs.com/smar ...

  3. 实现在easyui中的datagrid,点击某一列的列头弹出combobox下拉框

    easyUI  datagrid在列头加下拉框,实现对列内容的筛选. 代码: onLoadSuccess: function (data) {//Fires when data is loaded s ...

  4. Https握手协议以及证书认证

    1. 什么是https Https = http + 加密 + 认证 https是对http的安全强化,在http的基础上引入了加密和认证过程.通过加密和认证构建一条安全的传输通道.所以https可以 ...

  5. js应用之实现图片切换效果

    数组的操作与应用 数组的定义 var 数组名=new Array(); //创建空数组 var 数组名=new Array(size);//创建指定数组长度的数组 var 数组名=new Array( ...

  6. 2017-3-20 HTML 基础知识

    HTML的定义:HTML是一门编程语言的名字:超文本标记语言(Hyper Text Mark-up Language ),就是超越了文字的范畴,除了文字还可以有图片.视频.音频.动画.特效.表格.链接 ...

  7. servlet中的过滤器 国际化

    1. 过滤器 基本概念 过滤器是需要在xml中配置的. 为什么需用到过滤器? 项目开发中,经常会涉及到重复代码的实现! 注册 ----à Servlet [1. 设置编码] ----à  JSP 修改 ...

  8. PHP随机生成随机个数的字母组合示例

    在很多系统环境下大家都会用到字母组合各种编码,下面推荐大家非常实用的PHP代码. $num由几个字母组合. $s字母包含大小写,可以自己调配大写还小写. <?php function makec ...

  9. php从气象局获取天气预报并保存到服务器

    思路:1.打开网页时读取中国气象网的接口得到每个城市的该日json:2.解析并保存到mysql:3.客户端访问mysql得到数据集. 所包含的技巧: 进度条.flush()问题.mysql.xml.p ...

  10. React开发的一些注意点

    react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度.下面对一些react日常开发中的注意事项进行罗列.建议初学的朋友还是先过一遍这篇 ...