Java缓冲字节流复制文件的代码

对于机械硬盘来说,复制文件时,如果每次复制的数据比较小(比如几个字节),而量又特别大就会是个非常蛋疼的事情,效率非常非常的低,如果能够使用缓存一次性复制较大的数据(8~10K),那么就可以大大提高效率了。

而Java提供了带缓存的读写字节流BufferedInputstream和BufferedOutputsteam,那么通过这两个流复制文件可以提高文件复制的效率,因为通过缓存的方式可以一次性读取更多的字节数,然后再一次性写入更多的字节数,这样可以大大的降低硬盘的IO压力,从而提高复制效率。

Java中BufferedInputstream和BufferedOutputsteam默认的缓冲buff是8K,当然,我们也可以自定义buff,而经过测试(不严谨),发现自定义一个8K的buff比Java使用默认的8K的buff速度要快…而自定义buff的代码也不多,所以建议优先使用自定义buff的代码,那么代码如下:

public static void main(String[] args) {
	// 缓冲输入输出流
	// 在这里声明是为了能在finally中关闭
	BufferedInputStream bis = null;
	BufferedOutputStream bos = null;
	try {
		// 监控开始
		long start = new Date().getTime();
		System.out.println("开始复制...");

		// 要复制的文件
		File fileIn = new File("D:/filein.zip");
		// 创建文件输入流
		FileInputStream fis = new FileInputStream(fileIn);
		// 创建缓冲输入流
		bis = new BufferedInputStream(fis);
		
		// 复制到的位置及文件名
		File fileOut = new File("D:/fileout.zip");
		// 创建文件输出流
		FileOutputStream fos = new FileOutputStream(fileOut);
		// 创建缓冲输出流
		bos = new BufferedOutputStream(fos);

		// 设置buff 8K
		byte[] buff = new byte[8 * 1024];
		
		// 开始复制文件
		// 保存读取的字节数
		int size = -1; 
		// bis的read方法可以从流中读取指定的字节数(buff.length)存到到buff中
		// 并可以指定在buff中开始存放的位置(0,即第一个字节)
		// 最后返回实际读取到的字节数(size)
		while ((size = bis.read(buff, 0, buff.length)) != -1) {
			
			// bos的write方法可以从buff中取出指定字节数(size)的字节写入到流中
			// 并且可以指定从buff中开始取数据的位置(0,即第一个字节)
			bos.write(buff, 0, size);
		}
		// 当缓存buff满了会自动flush
		// 但是最后一次buff有可能不满,所以必须flush,
		// 否则文件可能少字节,就打不开了
		bos.flush();
		
		// 监控结束
		long end = new Date().getTime();
		System.out.println("复制结束!用时" + (end - start) + "ms。");
		
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		// 关闭流,切记,否则文件无法读写和删除
		// 关闭前需要判断null,否则可能出NullPointerException
		// 必须在finally中关, 否则有可能出异常后流没有关闭,
		// 	导致文件无法读写和删除
		try {
			if (bis != null) {
				bis.close();
				bis = null;
			}
			if (bos != null) {
				bos.close();
				bos = null;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

注意点:
1、buff不是越大越好,一般设置在8~10K比较合适。

2、复制文件时,一定要使用write(buff, 0, size),如果直接使用write(buff)可能会出现多复制字节的问题,因为最后一次buff很可能并没有被装满,如果使用write(buff)就会把整个buff的字节写入文件,即那些不属于文件的字节也被加到文件的最后了,对于文本文件还可能打开,但是对于exe文件就打不开了,切记,使用write(buff)是错误的!!!

3、文件复制完毕后,在while循环下面一定要flush()一次,也只用flush这一次,因为buff满了会自动flush,而最后一次buff不一定被装满,所以不会自动flush,如果没有flush可能造成复制的文件少了那么几K的字节…

4、流的关闭必须在finally中进行,否则在复制的过程中可能报错,然后程序就停止了,这个时候流有可能没有被关掉,会导致与复制相关的2个文件无法读写或删除。如果真发生这样的事情,就只有打开任务管理器,在“进程”栏找到“javaw.exe”,然后结束进程即可!

那么,就到这里吧!

本文《Java缓冲字节流复制文件的代码》来自 www.juwends.com ,欢迎转载或CV操作,但请注明出处,谢谢!