压缩字符流和字节流和全站压缩过滤器
1 public static void main(String[] args) throws Exception { 2 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //字符流 3 OutputStreamWriter osw = new OutputStreamWriter(bos); 4 PrintWriter pw = new PrintWriter(osw); 5 pw.write("helloworld"); 6 pw.flush(); 7 System.out.println(bos.toByteArray().length); 8 9 /* 10 * String s = "abcdefasdfasdfasdfasdfasdfasfd"; 11 * System.out.println("未压缩前:" + s.getBytes().length); 12 * 13 * ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 14 * 创建一个数组输出流. 15 * 16 * GZIPOutputStream gps = new GZIPOutputStream(baos);// 17 * 向baos字节数组流写入信息时,进行压缩 18 * 19 * gps.write(s.getBytes()); 20 * 21 * System.out.println("压缩后:" + baos.toByteArray().length); 22 * 23 * gps.close(); 24 * 25 * byte[] b = new byte[1024]; ByteArrayInputStream bis = new 26 * ByteArrayInputStream(baos.toByteArray()); 27 * 28 * GZIPInputStream gis = new GZIPInputStream(bis); 29 * 30 * int len = gis.read(b);// 将压缩数组中的信息解压读到b数组中。 31 * 32 * System.out.println(new String(b, 0, len)); 33 * 34 * gis.close(); 35 */ 36 }
全站压缩过滤器
![](//images0.cnblogs.com/i/227236/201405/270949354008968.jpg)
1 package cn.itcast.filter; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.OutputStreamWriter; 6 import java.io.PrintWriter; 7 import java.util.zip.GZIPOutputStream; 8 9 import javax.servlet.Filter; 10 import javax.servlet.FilterChain; 11 import javax.servlet.FilterConfig; 12 import javax.servlet.ServletException; 13 import javax.servlet.ServletOutputStream; 14 import javax.servlet.ServletRequest; 15 import javax.servlet.ServletResponse; 16 import javax.servlet.http.HttpServletRequest; 17 import javax.servlet.http.HttpServletRequestWrapper; 18 import javax.servlet.http.HttpServletResponse; 19 import javax.servlet.http.HttpServletResponseWrapper; 20 //全站压缩过滤器 21 public class GzipFilter implements Filter { 22 23 public void destroy() { 24 25 } 26 27 public void doFilter(ServletRequest req, ServletResponse resp, 28 FilterChain chain) throws IOException, ServletException { 29 HttpServletRequest request = (HttpServletRequest)req; 30 HttpServletResponse response = (HttpServletResponse)resp; 31 GzipHttpServletResponse gresponse = new GzipHttpServletResponse(response); 32 chain.doFilter(request, gresponse);//放行 33 //压缩代码写在此处 34 //找一个内存缓冲字节流 35 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 36 //把数据压缩到缓冲字节流流中 37 GZIPOutputStream gout = new GZIPOutputStream(baos); 38 //取出数据:压缩后的 39 byte b[] = gresponse.getOldBytes();//原始字节 40 System.out.println("原有数据大小:"+b.length); 41 42 //因为参数是byte b[]数组,所以会调用父类的write(byte[])方法,调用到最后 是write(int b)方法, 43 //而在父类中声明为抽象的,但是MyServletOutputStream实现了,并且在GzipHttpServletResponse对象中 44 //在doFilter()会被调用getOutputStream()函数进行操作进行写入输出流 45 gout.write(b); 46 gout.close();//保证所有的数据都进入内存缓存流 47 48 //取出压缩后的数据 49 b = baos.toByteArray(); 50 System.out.println("压缩后的数据大小:"+b.length); 51 //输出前一定要告知客户端压缩方式 52 response.setHeader("Content-Encoding", "gzip"); 53 response.setContentLength(b.length);//告知客户端正文的大小 54 //用服务器的响应对象输出 55 ServletOutputStream out = response.getOutputStream(); 56 out.write(b); 57 } 58 59 public void init(FilterConfig filterConfig) throws ServletException { 60 61 } 62 63 } 64 class GzipHttpServletResponse extends HttpServletResponseWrapper{ 65 private ByteArrayOutputStream baos = new ByteArrayOutputStream();//用于获取压缩前要输出的数据 66 private PrintWriter pw; 67 public GzipHttpServletResponse(HttpServletResponse response){ 68 super(response); 69 } 70 //把原始数据封装到一个缓冲流中 71 @Override 72 public ServletOutputStream getOutputStream() throws IOException { 73 return new MyServletOutputStream(baos); 74 } 75 76 //字符流:把原始数据封装到一个缓冲流中 77 @Override 78 public PrintWriter getWriter() throws IOException { //改写父方法,自己实现PrintWriter 79 pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));//字符流转成字节流编码会丢失 80 return pw; 81 } 82 //返回baos中的缓存数据:原始 83 public byte[] getOldBytes(){ 84 try { 85 if(pw!=null){ 86 pw.close(); 87 } 88 baos.flush(); 89 } catch (IOException e) { 90 e.printStackTrace(); 91 } 92 return baos.toByteArray(); 93 } 94 95 } 96 class MyServletOutputStream extends ServletOutputStream{ 97 private ByteArrayOutputStream baos; 98 public MyServletOutputStream(ByteArrayOutputStream baos){ 99 this.baos = baos; 100 } 101 @Override 102 public void write(int b) throws IOException { 103 baos.write(b); 104 } 105 }
如果调用response.getWriter()和response.getOutputStream()会抛异常,所以不能在代码中都调用,以上方法调用的getOutputStream和getWriter自己覆写了,没有调用servlet本身提供的,所以没有报异常。
把字节流和字符流全都放入ByteArrayOutputStream 缓冲中了,一并处理了。