黑马程序员技术交流社区

标题: java.util.zip.GZIPOutputStream实例答疑 [打印本页]

作者: 李靖    时间: 2012-10-25 11:06
标题: java.util.zip.GZIPOutputStream实例答疑
最近看到一段代码是用GZIP压缩Filter,具体代码有三部分
1
package com.helloweenvsfei.gzip;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GZipFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain chain) throws IOException, ServletException {
  HttpServletRequest request = (HttpServletRequest) req;
  HttpServletResponse response = (HttpServletResponse) res;
  String acceptEncoding = request.getHeader("Accept-Encoding");
  System.out.println("Accept-Encoding: " + acceptEncoding);
  if (acceptEncoding != null
    && acceptEncoding.toLowerCase().indexOf("gzip") != -1) {
   // 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据
   GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);
   chain.doFilter(request, gzipResponse);
   // 输出压缩数据
   gzipResponse.finishResponse();
  } else {
   // 否则, 不压缩
   chain.doFilter(request, response);
  }
}
public void init(FilterConfig arg0) throws ServletException {
}
}
2
package com.helloweenvsfei.gzip;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
public class GZipOutputStream extends ServletOutputStream {
private HttpServletResponse response;
// JDK 自带的压缩数据的类
private GZIPOutputStream gzipOutputStream;
// 将压缩后的数据存放到 ByteArrayOutputStream 对象中
private ByteArrayOutputStream byteArrayOutputStream;
public GZipOutputStream(HttpServletResponse response) throws IOException {
  this.response = response;
  byteArrayOutputStream = new ByteArrayOutputStream();
gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
}
public void write(int b) throws IOException {
  gzipOutputStream.write(b);
}
public void close() throws IOException {
  // 压缩完毕 一定要调用该方法
  gzipOutputStream.finish();
  // 将压缩后的数据输出到客户端
  byte[] content = byteArrayOutputStream.toByteArray();
  // 设定压缩方式为 GZIP, 客户端浏览器会自动将数据解压
  response.addHeader("Content-Encoding", "gzip");
  response.addHeader("Content-Length", Integer.toString(content.length));
  // 输出
  ServletOutputStream out = response.getOutputStream();
  out.write(content);
  out.close();
}
public void flush() throws IOException {
  gzipOutputStream.flush();
}
public void write(byte[] b, int off, int len) throws IOException {
  gzipOutputStream.write(b, off, len);
}

public void write(byte[] b) throws IOException {
  gzipOutputStream.write(b);
}
}
3.
package com.helloweenvsfei.gzip;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class GZipResponseWrapper extends HttpServletResponseWrapper {
// 默认的 response
private HttpServletResponse response;
// 自定义的 outputStream, 执行close()的时候对数据压缩,并输出
private GZipOutputStream gzipOutputStream;
// 自定义 printWriter,将内容输出到 GZipOutputStream 中
private PrintWriter writer;
public GZipResponseWrapper(HttpServletResponse response) throws IOException {
  super(response);
  this.response = response;
}
public ServletOutputStream getOutputStream() throws IOException {
  if (gzipOutputStream == null)
   gzipOutputStream = new GZipOutputStream(response);
  return gzipOutputStream;
}
public PrintWriter getWriter() throws IOException {
  if (writer == null)
   writer = new PrintWriter(new OutputStreamWriter(
     new GZipOutputStream(response), "UTF-8"));
  return writer;
}
// 压缩后数据长度会发生变化 因此将该方法内容置空
public void setContentLength(int contentLength) {
}
public void flushBuffer() throws IOException {
  gzipOutputStream.flush();
}
public void finishResponse() throws IOException {
  if (gzipOutputStream != null)
   gzipOutputStream.close();
  if (writer != null)
   writer.close();
}
}

通过查询JAVA API得知:
finish()
          完成将压缩数据写入输出流的操作,无需关闭基础流
[url=mk:@MSITStore:D:\20120617\学习资料\参考手册\JAVA%20API官方文档中文版.CHM::/java/util/zip/GZIPOutputStream.html#write(byte[], int, int)]write[/url](byte[] buf, int off, int len)
          将字节数组写入压缩输出流。
请问GZipOutputStream中的gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);是如何将数据压缩的,调用finish()的时候都完成了哪些动作呢?






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2