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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 赵晓东 于 2013-3-17 11:11 编辑
  1. /*IO_MyBufferedInputStream*/
  2. /*
  3.         需求:模拟字节读取流缓冲区

  4.         思路:字节读取流缓冲区是字节流在硬盘上读取一批数据然后存到数组中,计数器记录
  5.         住当前批次数据的个数,然后数组再通过指针来读取数据,每读取一个数据,计数器就
  6.         减一,直到读完当前批次的数据,缓冲区数组再次使用字节流在硬盘上读取一批数据,
  7.         以此类推,直到字节流把目标地址中的硬盘数据读完为止

  8.         步骤:
  9.         ①自定义字节读取缓冲区类MyBufferedInputStream,初始化该类时接收一个字节流对象
  10.         FileInputStream in;
  11.         ②定义计数器变量count和指针变量post
  12.         ③定义接收字符的数组buf
  13.         ④定义关闭资源对象myclose
  14. */

  15. import java.io.*;

  16. class MyBufferedInputStream
  17. {
  18.         FileInputStream in; //定义字节流对象的引用
  19.         int count = 0; //定义计数器
  20.         int post = 0; //定义指针
  21.         byte b = 0; //定义取出数组中数据的变量
  22.         byte[] buf = new byte[1024]; //定义缓存数组
  23.         MyBufferedInputStream(FileInputStream in)
  24.         {
  25.                 this.in = in; //接收一个字节流对象
  26.         }
  27.         
  28.         public int myRead() throws IOException
  29.         {
  30.                 if (count ==0) //如果计数器为0则说明缓存数组中没有数据,这时接收一批数据
  31.                 {
  32.                         count = in.read(buf); //接收一批数据存入到缓存数组中,并记录住个数
  33.                         post = 0; //指针为0,这里强调一下,如果不把指针重置为0的话,那么读取下一批次的时候,指针会越界
  34.                         b = buf[post]; //读取数据
  35.                         count--; //计数器自减,因为读取出一个元素,元素个数就会减少一个,直到把数组中的元素读完,才接收下一批次的数据
  36.                         post++; //指针累加,读取数组中的数据
  37.                         return b&255; //这里是(int) b强制转换了byte型的b
  38.                         /*
  39.                                 为什么把byte型的b 强制转换成int型的?
  40.                                         因为return 返回的是 int类型的
  41.                                 为什么不把返回值定义成byte型的呢?
  42.                                         因为如果文件读取到末尾返回的是-1,这个-1 是int型的

  43.                                 那为什么又要让强制转换后的b &255呢?
  44.                                         mp3的字节二进制文件有可能是1111-1111这样排列的,而这个值转换成十进制后是-1
  45.                                         byte型(8位):1111-1111(-1)
  46.                                         强制转换后
  47.                                         int型(32位):1111-1111 1111-1111 1111-11111 111-1111 (-1)
  48.                                         return返回-1程序就不会读取字符缓冲区的数据了,但是硬盘上的数据没有读完
  49.                                         这时我们就让提升后的int型 b与上255
  50.                                                 1111-1111 1111-1111 1111-1111 1111-1111
  51.                                               &0000-0000 0000-0000 0000-0000 1111-1111
  52.                                                    ————————————————————
  53.                                                 0000-0000 0000-0000 0000-0000 1111-1111 ——>保留的是后8位,也就是byte型数据的值,
  54.                                                 write写入时会自动将int型强制转换成byte型,到时候保留的就是,数组缓冲区中byte型的数据
  55.                         */
  56.                 }
  57.                 else if (count >0) //计数器不为0,说明数组中的元素没有完全取出,继续取出操作
  58.                 {
  59.                         b = buf[post];
  60.                         count--;
  61.                         post++;
  62.                         return b&0xFF;
  63.                 }
  64.                 else
  65.                         return -1; //如果read() 返回-1,则硬盘上的数据已经读取完毕,返回-1
  66.         }
  67.         public void myClose() throws IOException
  68.         {
  69.                 in.close(); //关闭资源
  70.         }
  71. }
  72. class MyBufferedInputStreamDemo
  73. {
  74.         public static void main(String[] args)
  75.         {
  76.                 long start = System.currentTimeMillis();
  77.                 CopyMp3();
  78.                 long end = System.currentTimeMillis();
  79.                 System.out.println(end-start+"毫秒");
  80.         }
  81.         public static void CopyMp3()
  82.         {
  83.                 MyBufferedInputStream mbis = null;
  84.                 BufferedOutputStream bos = null;
  85.                 int len = 0; //定义为int型,不能定义成byte,因为要接收文件读取结束的-1,而-1 是int 型的
  86.                
  87.                 try
  88.                 {
  89.                         mbis = new MyBufferedInputStream(new FileInputStream("d:\\1.mp3")); //使用自定义的缓冲区读取数据,传入一个字节流对象
  90.                         bos = new BufferedOutputStream(new FileOutputStream("d:\\3.mp3"));
  91.                         while ((len = mbis.myRead()) != -1)
  92.                         {
  93.                                 bos.write(len);
  94.                         }
  95.                 }
  96.                 catch (IOException e)
  97.                 {
  98.                         System.out.println(e.toString());
  99.                 }
  100.                 finally
  101.                 {
  102.                         try
  103.                         {
  104.                                 if(mbis != null)
  105.                                         mbis.myClose();
  106.                         }
  107.                         catch (IOException e)
  108.                         {
  109.                                 System.out.println(e.toString());
  110.                         }
  111.                         try
  112.                         {
  113.                                 if(bos != null)
  114.                                         bos.close();
  115.                         }
  116.                         catch (IOException e)
  117.                         {
  118.                                 System.out.println(e.toString());
  119.                         }
  120.                 }
  121.         }
  122. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

3 个回复

倒序浏览
你只是在模拟缓冲区,所以我觉得有一个地方你没说准确,就是你说len=0要定义为int类型是因为-1的原因,这里我的理解是:缓冲流是包装了FileInputstream流中的read方法实现的对文件读取操作,而FileInputStream的read方法本身会返回一个int类型的数据,所以不在缓冲流中不存在提升的问题了,这个提升在FileIputstream中已经完成;
其实缓冲区就是帮助我们定义了一个大小合适的数组来缓冲接收read方法的数据,而只要自己的byte数组大小合适,直接用FileIputstream的效率并不比加缓冲区的效率低,最后理解一下,自己定义一个byte数组接收数据相当于自己修了一个水池,而加入缓冲区,则系统又默认给了一个水池,这样就有两个水池了,到底是一个水池好,还是两个水池好,并不一定,但是可以肯定的是一定要有水池做缓冲。

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

回复 使用道具 举报
VOIDMAIN 发表于 2013-3-17 11:34
你只是在模拟缓冲区,所以我觉得有一个地方你没说准确,就是你说len=0要定义为int类型是因为-1的原因,这里 ...

恩,说的,很好,忘记read的返回值类型是int了{:3_49:}
回复 使用道具 举报
路过。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马