A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 吴扬 中级黑马   /  2012-6-27 20:57  /  1556 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 吴扬 于 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左右,为什么会出现这种情况?怎么使用缓冲区的流对象的效率反而降低了呢?


评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

6 个回复

倒序浏览
楼主将复制的数据量增大,比如100兆,这样效果就很明显了。
回复 使用道具 举报
韦念欣 发表于 2012-6-27 22:44
楼主将复制的数据量增大,比如100兆,这样效果就很明显了。

我也尝试着复制过一个大小为6M左右的MP3文件,但是还是这样的!这个应该不是偶然现象吧?
回复 使用道具 举报
吴扬 发表于 2012-6-27 22:50
我也尝试着复制过一个大小为6M左右的MP3文件,但是还是这样的!这个应该不是偶然现象吧? ...

第2种方法,你的代码每次只读1个字节,肯定比不上第1种方法一次读1024个字节了。
可以将第2种方法,也改成1次读1024个字节,然后再比较。
回复 使用道具 举报
韦念欣 发表于 2012-6-27 22:52
第2种方法,你的代码每次只读1个字节,肯定比不上第1种方法一次读1024个字节了。
可以将第2种方法,也改 ...

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

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

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

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

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
吴扬 中级黑马 2012-6-28 00:39:14
7#
韦念欣 发表于 2012-6-27 23:37
BufferedInputStream和BufferedOutputStream里面确实封装了一个临时数组作为缓冲区。

但是其实它的缓冲 ...

大概明白了,谢谢啦!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马