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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 李健09 于 2013-10-8 21:53 编辑
  1. package com.IO;
  2. /*
  3.          public static void copy_2() throws IOException
  4.         {
  5.                 MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("D:\\歌曲\\红颜白头到.wma"));
  6.                 BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\歌曲\\copy2.wma"));
  7.                 int by=0;
  8.                 //sop("第一个字节"+bufis.myRead()); //此时 显示的结果字节数很少  第一个字节48
  9.                 while((by=bufis.myRead())!=-1)
  10.                 {
  11.                         bufos.write(by);
  12.                 }
  13.                 bufos.close();
  14.                 bufis.myClose();
  15.         }
  16. ----sop("第一个字节"+bufis.myRead()); //此时 显示的结果字节数很少  第一个字节48,那么我们的程序接近-1的时间就会很快
  17.         
  18.         public int myRead()        throws IOException
  19.         {
  20.                 //通过in对象读取硬盘上的数据,并存储buf中。
  21.                 if(count==0)
  22.                 {
  23.                         count=in.read(buf);//这里表示in.read()读取读取硬盘上的数据,并存储于buf中的个数
  24.                         if(count<0)
  25.                                 return -1;
  26.                         pos=0;
  27.                         byte b=buf[pos];
  28.                         count--;
  29.                         pos++;
  30.                         return b;
  31.                 }
  32.                 else if(count>0)
  33.                 {
  34.                         byte b=buf[pos];
  35.                         count--;
  36.                         pos++;
  37.                         return b;
  38.                 }
  39.                 return -1;
  40.         }
  41.         
  42. ----当读到byte(b)值为111111时,返回的是-1 转换成int 还是-1 ;copy_2()方法就会停止,程序停止运行,复制也停止运行,所以没有完全复制完成
  43.         -1 ----->1111-1111二进制
  44.         byte:-1------>int:-1;
  45.         byte:-1
  46.         1111-1111
  47.         int:-1
  48.         1111-1111  1111-1111  1111-1111  1111-1111
  49.         那为什么myRead()方法的返回值用的是int呢?
  50.         在读到连续11111111的时候为了避免碰到-1的这种情况和我判断的结束截止标记-1相同所以我可以在保留原11111111的基础上再转成int类型的时候
  51.         11111111前面补零而不补1,避免类提前使结束标记变成-1;使原数据没有变化并避免提前出现-1的情况
  52.         byte[b]:-1
  53.         1111-1111
  54.         byte[b]---->int类型 那不还是-1吗?因为我们在1111-1111前面补得是1导致的,那么我们只要在前面补0即可保留原字节数据不免又可以避免-1的
  55.         出现,那么我们怎么补0呢?
  56.         0000-0000  0000-0000  0000-0000 1111-1111    ---->255
  57.         int 类型的-1 取最低8位(-1&255)
  58.                 1111-1111  1111-1111  1111-1111  1111-1111
  59.                 0000-0000  0000-0000  0000-0000  1111-1111
  60.         &
  61.         ---------------------------------------------
  62.                 0000-0000  0000-0000  0000-0000  1111-1111
  63.         所以b&255
  64. */
  65. import java.io.*;
  66. class MyBufferedInputStream
  67. {
  68.         private InputStream in;
  69.         private byte[] buf=new byte[1024];
  70.         int pos=0,count=0;
  71.         MyBufferedInputStream(InputStream in)
  72.         {
  73.                 this.in=in;
  74.         }
  75.         //一次读一个字节,从缓冲区(字节数组)获取
  76.         public int myRead()        throws IOException
  77.         {
  78.                 //通过in对象读取硬盘上的数据,并存储buf中。
  79.                 if(count==0)
  80.                 {
  81.                         count=in.read(buf);//这里表示in.read()读取读取硬盘上的数据,并存储于buf中的个数
  82.                         if(count<0)
  83.                                 return -1;
  84.                         pos=0;
  85.                         byte b=buf[pos];
  86.                         count--;
  87.                         pos++;
  88.                         return b&255;
  89.                 }
  90.                 else if(count>0)
  91.                 {
  92.                         byte b=buf[pos];
  93.                         count--;
  94.                         pos++;
  95.                         return b&0xff;//0xff  255的16进制表现形式
  96.                 }
  97.                 return -1;
  98.         }
  99.         public void myClose() throws IOException
  100.         {
  101.                 in.close();
  102.         }
  103. }
  104. public class MyBufferedInputStreamDemo
  105. {
  106.         public static void main(String[] args) throws IOException
  107.         {
  108.                 long start =System.currentTimeMillis();
  109.                 copy_2();
  110.                 long end=System.currentTimeMillis();
  111.                 sop((end-start)+"毫秒");

  112.         }
  113.         public static void copy_2() throws IOException
  114.         {
  115.                 MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("D:\\歌曲\\红颜白头到.wma"));
  116.                 BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\歌曲\\copy2.wma"));
  117.                 int by=0;
  118.                 //sop("第一个字节"+bufis.myRead());
  119.          while((by=bufis.myRead())!=-1)
  120.                 {
  121.                         bufos.write(by);
  122.                 }
  123.                 bufos.close();
  124.                 bufis.myClose();
  125.         }
  126.         public static void sop(Object obj)
  127.         {
  128.                 System.out.println(obj);
  129.         }
  130. }
复制代码
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标记-1吗?
问题2:我上面注释整理的笔记思路对吗?还有怎么是b&255,这里的b不是byte类型的吗?不是int类型的取最低8位吗?这时的怎么可以取最低8位?

评分

参与人数 1技术分 +1 收起 理由
黄文伯 + 1 很给力!

查看全部评分

4 个回复

正序浏览
本帖最后由 李健09 于 2013-10-8 21:52 编辑
hanfei2511 发表于 2013-10-4 05:40
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标 ...

谢谢:):)
回复 使用道具 举报
亲,如问题已解决请将分类的“未解决”改为“已解决”。
以后的问题贴也要及时更改分类哦~
回复 使用道具 举报
问题1:sop("第一个字节"+bufis.myRead()); 我的这段代码输出的是第一个字节48是表示过48个字节就是结束标记-1吗?
问题2:我上面注释整理的笔记思路对吗?还有怎么是b&255,这里的b不是byte类型的吗?不是int类型的取最低8位吗?这时的怎么可以取最低8位?
第一个问题:
不是的,首先myRead()返回的是一个字节的数据(当然是以int类型返回的)
public int myRead() throws IOException {
                if(count==0){
                        count=in.read(buf);//因为你定义的buf的长度是1024,所以,此处的count值是1024,即当count等于0时,会从输入流读取1024个字节的数据,存储在buf数组中,如果你的文件大小小于1024字节,那么就会占用小于1024字节的数组空间,如果大于1024那么当elseif语句中count自减等于0后,会重新回到if语句块,再次进行上述相同的过程。如果读到了文件的结尾,返回-1
                        if(count<0)
                                return -1;
                        pos=0;
                        byte b=buf[pos];//b存储的是buf中第一个字节的数据
                        count--;//此时count==1023,所以下次调用myRead方法时,会执行elseif 部分语句。如果读到文件末尾,返回-1
                        pos++;//pos加一之后,指向buf数组中的下一个位置。
                        return b&255;//以int类型将b的数据返回。
                }
                else if(count>0)
                {
                        byte b=buf[pos];
                        count--;
                        pos++;
                        return b&0xff;//0xff
                }
                return -1;
        }

所以你在后面的while循环中调用myRead方法时,每一次返回的是当前字节的数据,你第一次调用返回的48表示当前字节数据是48,而不是48字节的数据,通过上面分析,我们也知道读完这个字节数据之后,也不是结束标记-1,而是buf数组存储的下一字节的数据。除非你的文件只有一字节的数据。你可以在copy_2()方法的sop语句后多加几条sop语句看下48后面的几个字节的 数据内容是什么。
第二个问题:
因为write()方法是以int类型写入文件的,所以我们需要将读取的byte类型数据转换成int类型。如果不进行&255计算,那么java会通过补码来进行自动转换,就会出现你在注释中说到的文件提前终止(出现-1)的情况,当进行&255或&0xff就会没问题了。所以你的注释部分还是对的。
至于“还有怎么是b&255,这里的b不是byte类型的吗?不是int类型的取最低8位吗?这时的怎么可以取最低8位?”不太明白你疑惑的是什么,&是按位与,是利用二进制进行运算的,这里原本8位的b,在其前面补充1,到32位,和32位表示的255进行与运算,结果自然是保存了b原始8位的数据信息,只是这时在其最高位前加了24个零而已。
不知有没有讲明白,希望对您有帮助。

评分

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

查看全部评分

回复 使用道具 举报 1 0
达人们速来
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马