io字节流拷贝字节文件效率测试

00 前言


楼主作为一个半路出家的程序员,各种知识的学习几乎都是入快刀斩乱麻,野蛮生长出来的。最近疫情期间,在家呆着无聊,着手关注一写底层的的基础的东西,突然发现很多以前不太明白的东西仿佛犹如雨后彩虹,豁然开朗。于是又闲来写了一些小tips或者小案例吧,反正闲着也是闲着,权当练习打字速度了呗。
好了,废话部队说,言归正传吧,开始楼主人生之中的第一篇博客吧

加下来要做的事情如下

1.测试普通字节流(逐个字节)复制
2.测试普通字节流(自定义小数组复制)复制:小数组大小为8*1024
2.缓冲区字节流复制的效率
4.缓冲区字节流复制(加上数组)复制的效率
4.使用jdk7标准流异常处理代码

02 代码


废话就不说了,直接上代码吧

1.代码都是相当完整的,直接复制改一下路径就可以用

/**
 * 案例1: 各种方式拷贝文件效率测试(字节流拷贝文件)
 * 		要求:1.普通字节流(单字节复制与定义小数组复制)复制与缓冲去字节流复制大文件的效率
 *	 		2.使用jdk7标准流异常处理代码
 * 
 * @author yzm
 *
 */
public class DemoBufferedStream {

	/**
	 *
		
	 */
	public static void main(String[] args)  {
		// TODO Auto-generated method stub
		copyByStream();
		copyByStream2();
		copyByBfferedStream();
		copyByBfferedStream2();
		//内存溢出演示
		copyByStream3();
		
	}

	/**
	 * 普通字节流定义小数组拷贝文件
	 */
	public static void copyByStream() {
		// 开始记录时间
		long start = System.currentTimeMillis();
		try (
				FileInputStream fis = new FileInputStream("E://image//a.mp3");
				FileOutputStream fos = new FileOutputStream("E://image2//a.mp3");
			) {
				// 读写数据
				int b;
				while ((b = fis.read()) != -1) {
					fos.write(b);
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
		//结束时间
		long end = System.currentTimeMillis();
		System.out.println("普通字节流复制时间: " + (end - start) + " 毫秒 ");
	}
	/**
	 * 缓冲区字节流拷贝文件
	 */
	public static void copyByBfferedStream(){

		// 开始记录时间
		long start = System.currentTimeMillis();
		try (
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E://image//a.mp3"));
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E://image2//b.mp3"));
			) {
				// 读写数据
				int b;
				while ((b = bis.read()) != -1) {
					bos.write(b);
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
		//结束时间
		long end = System.currentTimeMillis();
		System.out.println("缓冲字节流复制时间: " + (end - start) + " 毫秒 ");
	}
	public static void copyByStream2() {
		// 开始记录时间
		long start = System.currentTimeMillis();
		try (
				FileInputStream fis = new FileInputStream("E://image//a.mp3");
				FileOutputStream fos = new FileOutputStream("E://image2//c.mp3");
			) {
				//变量len用来记录读取的有效字节数
				int len = 0;
				// 定义字节数组,作为装字节数据的容器
				byte[] b = new byte[8*1024];
				while ((len = fis.read(b)) != -1) {
					fos.write(b, 0, len);;
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
		//结束时间
		long end = System.currentTimeMillis();
		System.out.println("普通字节流自定义小数组复制时间复制时间: " + (end - start) + " 毫秒 ");
	}
	public static void copyByBfferedStream2(){

		// 开始记录时间
		long start = System.currentTimeMillis();
		try (
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E://image//a.mp3"));
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E://image2//d.mp3"));
			) {
				int len = 0;
				// 定义字节数组,作为装字节数据的容器
				byte[] b = new byte[8*1024];
				while ((len = bis.read(b)) != -1) {
					bos.write(b, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
		//结束时间
		long end = System.currentTimeMillis();
		System.out.println("缓冲字节流自定义数组复制时间: " + (end - start) + " 毫秒 ");
	}
	public static void copyByStream3() {
		// 开始记录时间
		long start = System.currentTimeMillis();
		try (
				FileInputStream fis = new FileInputStream("f://Win10x64-2019.01.rar");
				FileOutputStream fos = new FileOutputStream("f://Win10x64-2019.01.2.rar");
			) {
				//变量len用来记录读取的有效字节数
				int len = 0;
				// 定义字节数组,作为装字节数据的容器
				byte[] b = new byte[1024*1024*1024];
				while ((len = fis.read(b)) != -1) {
					fos.write(b, 0, len);;
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("自定义大数组数组复制时间: " + (end - start) + " 毫秒 ");
	}
	
}

03 运行结果以及分析


运行结果

1普通字节流复制时间: 24610 毫秒
2.普通字节流自定义小数组复制时间复制时间: 12 毫秒
3.缓冲字节流复制时间: 144 毫秒
4.缓冲字节流自定义数组复制时间: 17 毫秒
5.Exception in thread “main” java.lang.OutOfMemoryError

分析

  • 0.普通字节流逐个字节读写时,很显然是慢到令人发指的,对于此数测试完全是重在参与而已,故对此种方式不作任何讨论。
  • 1.字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式),所以提供了字节缓冲区流BufferedInputStreamBufferedOutputStream
  • 2.两者都内置了一个缓冲区(数组)。从BufferedInputStream中读取一个字节时。BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个。程序再次读取时, 就不用找文件了, 直接从缓冲区中获取。直到缓冲区中所有
    的都被使用过, 才重新从文件中读取8192个.
  • 3.BufferedOutputStream也内置了一个缓冲区(数组)。程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中。直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
  • 4.使用缓冲区字节流读和写文件就一定比普通复制效率高吗,从测试结果来看显然不是一定的
    原因:普通字节流复制文件是,我自定义了一个81024的小数组,而字节流内置的缓冲区数组大小是81024,虽然数组大小都一样,但是效率上普通字节流比缓冲字节流复制效率略高,因为BufferedInputStreamBufferedOutputStream都内置了一个8*1024大小的数组作为缓冲区,所以缓冲区字节流复制文件至少操作了两个数组,而普通字节流定义小数组方式读和写都只操作一个数组,所以小略高。
  • 5.单纯使用缓冲字节流好像效率依然比普通字节流自定义小数组差了很多,可见,虽然缓冲字节流内置了大小为8*1024的字节数组,但是如果不结合系定义数组使用,依然达不到理想的效率,也就能只能KO一下普通字节流逐个字节读写的情况了。
  • 6.既然缓冲流都有内置数组了,为什么还是需要自定义数组呢? 关于这点楼主也正在研究源码查找具体原因,有结果了会更新博客,也欢迎网友留言,一起研究,一起进步。
  • 7.那是不是自定义的数组越大越好呢?显然不是的,因为可能导致内存溢出,报如下错误:
    Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

04 结语


如果不知道我在说什么,那个人强烈建议快快复习一下java基础,编程学习,每一个地方都是重点

别因为非得太高,就忘了为什么出发。
高楼大厦平地起,任何建筑,别管修得多么多高大上,打地基绝对是最重要的

你可能感兴趣的:(java基础)