首页 > 代码库 > JDK之BufferedInputStream分析
JDK之BufferedInputStream分析
最近写了一个下载文件的功能。
因为文件是在另一台服务器上面,所以要读取网络文件,需用到HttpURLConnection类。
先贴出来代码。
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.*; public class downloadServlet extends HttpServlet { protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException{ String file=request.getParameter("fileUrl"); //得到网络文件的地址 response.addHeader("Content-Disposition","attachment;filename='"+file+"'"); OutputStream os = null; InputStream in = null; try { URL url = new URL(file); HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); in = urlConnection.getInputStream(); //获得流 BufferedInputStream fis = new BufferedInputStream(in); //BufferedInputStream装饰InputStream os = response.getOutputStream(); int i = -1; byte[] b = new byte[1024]; while((i = fis.read(b, 0, 1024)) != -1){ //读字节 os.write(b, 0, i); } fis.close(); urlConnection = null; url = null; } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); if(in!=null) in.close(); } catch (IOException e) { e.printStackTrace(); } } } protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException{ doGet(request,response); } }
而其中又用到了BufferedInputStream这个类,然后就研究了一下这个类。
BufferedInputStream"装饰"了InputStream的内部工作方式,使得流的读入操作使用缓冲机制。在使用了缓冲机制后,不会对每一次的流读入操作都产生一个物理的读动作,从而提高了效率。在涉及到物理流的读入时,都应当使用这个装饰流类。
先看一下read方法的源码
public synchronized int read() throws IOException { if (pos >= count) { fill(); //此时需要先去物理位置读一段出来 if (pos >= count) //如果仍然没有读出来,则表明已经没有可读的了 return -1; //返回-1 } return getBufIfOpen()[pos++] & 0xff; }pos要读的位置,count就是总共有多少个字节
在看一下fill方法
private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos < 0) pos = 0; /* no mark: throw away the buffer */ else if (pos >= buffer.length) /* no room left in buffer */ if (markpos > 0) { /* can throw away early part of the buffer */ int sz = pos - markpos; System.arraycopy(buffer, markpos, buffer, 0, sz); pos = sz; markpos = 0; } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ } else { /* grow buffer */ int nsz = pos * 2; if (nsz > marklimit) nsz = marklimit; byte nbuf[] = new byte[nsz]; System.arraycopy(buffer, 0, nbuf, 0, pos); if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { // Can't replace buf if there was an async close. // Note: This would need to be changed if fill() // is ever made accessible to multiple threads. // But for now, the only way CAS can fail is via close. // assert buf == null; throw new IOException("Stream closed"); } buffer = nbuf; } count = pos; int n = getInIfOpen().read(buffer, pos, buffer.length - pos); if (n > 0) count = n + pos; }然后注意下这句话n = getInIfOpen().read(buffer, pos, buffer.length - pos);
这就是从物理位置读的
实际上就是调用的InputStream类的read方法,这就是装饰模式的运用
public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = read(); if (c == -1) { return -1; } b[off] = (byte)c; int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; }
JDK之BufferedInputStream分析
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。