首先是文件输入及输出流的基本使用
public static void test1() throws Exception {
long start = System.currentTimeMillis();
File fromFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
File toFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/11[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
FileInputStream fileInputStream = new FileInputStream(fromFile);
FileOutputStream fileOutputStream = new FileOutputStream(toFile);
byte[] bytes = new byte[1024];
int read;
while ((read = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, read);
}
fileOutputStream.close();
fileInputStream.close();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
在代码中我们用到了自定义的“缓冲区”,将文件读入的字节数据放到bytes数组中,然后批量的写入到输出流
其中fileInputStream.read(bytes)的返回值是读取到数据的长度
复制文件耗时12秒
然后加入缓冲流
public static void test2() throws Exception {
long start = System.currentTimeMillis();
File fromFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
File toFile = new File("/Users/mouxiaoshi/IdeaProjects/pro-test/11[BD影视分享bd2020.com]电u惊魂8.Jigsaw.2017.HD720P.中英双字.mp4");
FileInputStream fileInputStream = new FileInputStream(fromFile);
FileOutputStream fileOutputStream = new FileOutputStream(toFile);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] bytes = new byte[1024];
int len;
while ((len = bufferedInputStream.read(bytes, 0, bytes.length)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
bufferedOutputStream.close();
bufferedInputStream.close();
fileOutputStream.close();
fileInputStream.close();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
复制文件耗时3.5秒
BufferedInputStream中定义了用于储存数据的缓冲区(数组)
protected volatile byte buf[];
当未指定数组的大小是,默认的大小为8192
private static int DEFAULT_BUFFER_SIZE = 8192;
先来看下bufferedInputStream的读操作
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
当读取的位置大于或等于bufferedInputStream中缓重区有限数据标志位时,说明bufferedInputStream中的数据已经读完了,需要填充数据
private void fill() throws IOException {
//获取缓冲区
byte[] buffer = getBufIfOpen();
//判断是否标记
if (markpos < 0)
//未标记
pos = 0;
else if (pos >= buffer.length)
//已读完
if (markpos > 0) {
//有标记的部分,丢弃不需要的的部分(未标记的部分)标记由mark方法执行标记
int sz = pos - markpos;
//复制标记部分到头位置
System.arraycopy(buffer, markpos, buffer, 0, sz);
//读取的位置为标志位置的结尾
pos = sz;
//标记位置为0
markpos = 0;
} else if (buffer.length >= marklimit) {
//意味着markPos已经失效,用户不可以在进行reRead
//1. pos位置大于等于缓存长度,且markPos等于零,此时的 pos >= buffer.length 而 buffer.length >= marklimit
// 故(pos-markPos) = pos > markLimit,也就是说根据 marklimit字段的描述
// Whenever the difference between pos and markpos exceeds marklimit, then the mark may be dropped by setting markpos to -1.
//此时buffer的标记位时无效的
markpos = -1;
pos = 0;
} else if (buffer.length >= MAX_BUFFER_SIZE) {
//大于最大的缓冲大小
throw new OutOfMemoryError("Required array size too large");
} else {
//扩容
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
pos * 2 : MAX_BUFFER_SIZE;
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;
}