赞
踩
import java.io.*; /** * 分别用普通数据流和带缓冲区的数据流复制一个167M的数据文件 * 通过用时比较两者的工作效率 * @author Zues * */ public class CopyMp3 { private static File file = new File("D:\\1.mp4"); private static File file_cp = new File("D:\\1_cp.mp4"); // FileInputStream复制 public void copy() throws IOException { FileInputStream in = new FileInputStream(file); FileOutputStream out = new FileOutputStream(file_cp); int len = 0; while ((len = in.read(buf)) != -1) { out.write(buf); } in.close(); out.close(); } // BufferedStream复制 public void copyByBuffer() throws IOException { BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file_cp)); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) { out.write(buf); } in.close(); out.close(); } public static void main(String[] args) throws IOException { CopyMp3 copy=new CopyMp3(); long time1=System.currentTimeMillis(); copy.copy(); long time2=System.currentTimeMillis(); System.out.println("直接复制用时:"+(time2-time1)+"毫秒"); long time3=System.currentTimeMillis(); copy.copyByBuffer(); long time4=System.currentTimeMillis(); System.out.println("缓冲区复制用时:"+(time4-time3)+"毫秒"); } }
上述InputStream使用了byte[] buf = new byte[1024]; 作为read方法的缓冲区。根据运行结果可以知道InputStream的缓冲区与BufferedInputStream的缓冲区是不一样的。那么现在通过查看源码来分析两者有什么不一样。
FileInputStream
package java.io; public class FileInputStream extends InputStream{ /** *从输入流中读取一个字节 *该方法为private私有方法,用户不能直接调用。 *该方法为native本地方法,这是因为Java语言不能直接与操作系统或计算机硬件交互, *只能通过调用C/C++编写的本地方法来实现对磁盘数据的访问。 */ private native int read0() throws IOException; public int read() throws IOException { Object traceContext = IoTrace.fileReadBegin(path); //指向Path int b = 0; try { b = read0(); //调用read0()方法 } finally { IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1); //从Path读出b=read0() } return b; } /** * 从输入流中读取多个字节到byte数组中 * 该方法也是私有本地方法,不对用户开放,只供内部调用。 */ private native int readBytes(byte b[], int off, int len) throws IOException; //调用native方法readBytes(b, 0, b.length)每次读取多个字节 public int read(byte b[]) throws IOException { Object traceContext = IoTrace.fileReadBegin(path); int bytesRead = 0; try { bytesRead = readBytes(b, 0, b.length); //每次读取缓冲区全部的 } finally { IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); } return bytesRead; } }
BufferedInputStream
package java.io; public class BufferedInputStream extends FilterInputStream { private static int defaultBufferSize = 8192; //缓冲区数组默认大小8192Byte,也就是8K protected volatile byte buf[]; //内部缓冲数组,会根据需要进行填充,大小默认为8192字节,也可以用构造函数自定义大小 protected int count; //当count=0时,说明缓冲区内容已读完,会再次填充 protected int pos; // 缓冲区指针,记录缓冲区当前读取位置 private InputStream getInIfOpen() throws IOException { InputStream input = in; if (input == null) throw new IOException("Stream closed"); return input; } //创建空缓冲区 private byte[] getBufIfOpen() throws IOException { byte[] buffer = buf; if (buffer == null) throw new IOException("Stream closed"); return buffer; } //创建默认大小的BufferedInputStream public BufferedInputStream(InputStream in) { this(in, defaultBufferSize); } //此构造方法可以自定义缓冲区大小 public BufferedInputStream(InputStream in, int size) { super(in); if (size <= 0) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; } private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos < 0) pos = 0; //....部分源码省略 count = pos; int n = getInIfOpen().read(buffer, pos, buffer.length - pos); if (n > 0) count = n + pos; } /** * 读取一个字节 * 与FileInputStream中的read()方法不同的是,这里是从缓冲区数组中读取了一个字节 * 也就是直接从内存中获取的,效率远高于前者 */ public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; } //从缓冲区中一次读取多个字节 private int read1(byte[] b, int off, int len) throws IOException { int avail = count - pos; if (avail <= 0) { if (len >= getBufIfOpen().length && markpos < 0) { return getInIfOpen().read(b, off, len); } fill(); avail = count - pos; if (avail <= 0) return -1; } int cnt = (avail < len) ? avail : len; System.arraycopy(getBufIfOpen(), pos, b, off, cnt); pos += cnt; return cnt; } public synchronized int read(byte b[], int off, int len){ //为减少文章篇幅,源码就不显示了 } }
结论:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。