黑马程序员技术交流社区

标题: IO中两种方式复制图片的效率问题 [打印本页]

作者: 吴扬    时间: 2012-6-27 20:57
标题: IO中两种方式复制图片的效率问题
本帖最后由 吴扬 于 2012-6-28 00:39 编辑

下面是两段复制图片文件的代码,第一个没有用到缓冲区,而第二个则用到了
  1. public static void copyFile() throws IOException
  2.         {
  3.                 FileInputStream fis = null;
  4.                 FileOutputStream fos = null;
  5.                
  6.                         fis = new FileInputStream("d:\\russel.jpg");
  7.                         fos = new FileOutputStream("d:\\russel_copy.jpg");
  8.                         
  9.                         byte[] buf = new byte[1024];
  10.                         
  11.                         int len = 0;
  12.                         
  13.                         while((len = fis.read(buf)) != -1)
  14.                         {
  15.                                 fos.write(buf, 0, len);
  16.                         }
  17.                 }
复制代码
第一种方法没有用到缓冲区流对象,复制一个大小为208k的图片文件,需要的时常每次大概在4ms左右
  1. public static void copyFileByBuf() throws IOException
  2.         {
  3.                 BufferedInputStream bufferedFis = new BufferedInputStream(new FileInputStream("d:\\russel.jpg"));
  4.                 BufferedOutputStream bufferedFos = new BufferedOutputStream(new FileOutputStream("d:\\russel_copy.jpg"));
  5.                
  6.                         
  7.                         int ch = 0;
  8.                         
  9.                         while((ch = bufferedFis.read()) != -1)
  10.                         {
  11.                                 bufferedFos.write(ch);
  12.                         }
  13.         }
复制代码
第二种方式则用到了缓冲区流对象,复制一个相同的图片文件,但是每次运行的结果都在13ms左右,为什么会出现这种情况?怎么使用缓冲区的流对象的效率反而降低了呢?



作者: 韦念欣    时间: 2012-6-27 22:44
楼主将复制的数据量增大,比如100兆,这样效果就很明显了。
作者: 吴扬    时间: 2012-6-27 22:50
韦念欣 发表于 2012-6-27 22:44
楼主将复制的数据量增大,比如100兆,这样效果就很明显了。

我也尝试着复制过一个大小为6M左右的MP3文件,但是还是这样的!这个应该不是偶然现象吧?
作者: 韦念欣    时间: 2012-6-27 22:52
吴扬 发表于 2012-6-27 22:50
我也尝试着复制过一个大小为6M左右的MP3文件,但是还是这样的!这个应该不是偶然现象吧? ...

第2种方法,你的代码每次只读1个字节,肯定比不上第1种方法一次读1024个字节了。
可以将第2种方法,也改成1次读1024个字节,然后再比较。
作者: 吴扬    时间: 2012-6-27 23:18
韦念欣 发表于 2012-6-27 22:52
第2种方法,你的代码每次只读1个字节,肯定比不上第1种方法一次读1024个字节了。
可以将第2种方法,也改 ...

在这个缓冲区内部不是也封装了一个字节数组作为临时存储的作用么?这个作为临时存储的字节数组java定义的是多大呢?这个毕老师在视频中好像没讲!
作者: 韦念欣    时间: 2012-6-27 23:37
吴扬 发表于 2012-6-27 23:18
在这个缓冲区内部不是也封装了一个字节数组作为临时存储的作用么?这个作为临时存储的字节数组java定义的 ...

BufferedInputStream和BufferedOutputStream里面确实封装了一个临时数组作为缓冲区。

但是其实它的缓冲作用不仅仅是封装了这个数组,还有其他的作用。
BufferedInputStream对象在使用的过程中,若CPU空闲或暂时不是使用它,那就会偷偷在后台先把数据从硬盘读入到缓冲区中,这样当你突然来读取数据时,就直接从缓冲区中读取,节省了一些时间。
BufferedOutputStream对象在使用的过程中,将写入的数据先写入到缓冲区的,等到用户flush或缓冲区满,才真正一次性写入硬盘。

但是,楼主如果一个一个字节的读取数据,及时你是从缓冲区中读取的,别人一次读取1024字节,你一个一个来,至少也要循环1024次,条件判断1024次,1024次读取操作,就会慢了。所以,不管怎么样,楼主应该要一次性读取多个数据,这样才能达到优化的效果。


作者: 吴扬    时间: 2012-6-28 00:39
韦念欣 发表于 2012-6-27 23:37
BufferedInputStream和BufferedOutputStream里面确实封装了一个临时数组作为缓冲区。

但是其实它的缓冲 ...

大概明白了,谢谢啦!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2