黑马程序员技术交流社区

标题: MyBuffereInStream [打印本页]

作者: 程有愿    时间: 2012-9-4 19:04
标题: MyBuffereInStream
问题的描述我写在图片上了,还有就是为什么非要把myRead方法的返回值定义为int型不定义为byte型呢?希望哪位大虾帮我看看!

SR`Y(VWFLOTX4@8K8@M5BCQ.jpg (166.33 KB, 下载次数: 11)

SR`Y(VWFLOTX4@8K8@M5BCQ.jpg

作者: 周兴华    时间: 2012-9-4 20:06
本帖最后由 周兴华 于 2012-9-4 20:07 编辑

这段视频中的代码是毕老师写出BufferedInputStream的read方法的原理。改read方法为重写了InputStream的read方法,重写后的read方法作用是一次读一个字节,从缓冲区(字节数组)获取。
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int?
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。

楼主首先要清楚byte型数据连续8个1为什么是-1?
0000 0001  //这个是1
1111 1110  //按位取反
1111 1111 //将按位取反后的数据再加上1就是其负数也就是-1了。

为什么要将b&255?
因为原来InputStream的read方法每次读一个字节的数据,那么就有可能会读到连续8个1的情况,而连续8个1以byte型表示为-1,在做了int型的提升后还是-1,因为他会对前面24位补齐为1,也就是变成了11111111 11111111 11111111 11111111,而我们判断读取结束是通过结尾标记-1来确定的,这个字节的数据又是有效的,显然我们要避免。所以要与上一个255.即
11111111 11111111 11111111 11111111  //读取到的连续8个1的数据做int型提升后的结果
00000000 00000000 00000000 11111111  //255
00000000 00000000 00000000 11111111  //&255以后就保留了低8位,也就是我们要的数据。

&是按位操作符,只有1&1的结果为1,1&0,0&1或0&0的结果都是0.
作者: 张 涛    时间: 2012-9-4 21:39
1.返回值用int,而不用byte的原因:
     因为在内存中,数据的存在形式是二进制,一个字节,一个byte的内容无非就是0000 0000,0000 0001,0000 0010,,,,或者1111 1111等。而这些这些数据都是以补码的形式存在的,而补码的换算,下面讲。1111 1111是-1的补码,如果返回值类型用byte,那么就相当于遇到1111 1111的内存但愿返回,但是内存中确确实实很可能存在1111 1111这种形式,遇到它返回,那么很可能没到最后,所以返回值不能是byte,而是int。

2.补码的换算:
最高位为1,表示负数。
正数的补码取反加1后为其负数对应的补码;负数的补码取反加1后,为其绝对值。
1111 1111的最高位为1,是负数,它的补码取反加1是0000 0001,为1,其绝对值,所以1111 1111是-1的补码。

3.为什么不直接转换为int类型,而用与0x000000ff相与的方式转换。
如果强制转换,1111 1111的byte类型,转换为int类型,这种转换一定是保持值不变的,所以还是-1,也就是转换为了11111111 11111111 11111111 111111.这种方法无效。
而用与0x000000ff相与的方式,其实是与00000000 0000000 00000000 11111111相与。如果为-1,也就是1111 1111,那么相与后的值是:
   00000000 00000000 00000000 11111111  //这是0x000000ff
&                                              11111111  //这是-1
------------------------------------------------------------------
  00000000 00000000 00000000 11111111
这个值,也是补码,但不是-1的补码,也就是说相与后,其值发生了改变。

但是对于我们的程序来说,没关系,因为得到返回的int之后,会用write方法写出去,而这个方法的参数虽然是int类型,但它只会写int类型的低8位,也就是1111 1111,这样在读入和写出时都不变,程序还是正确的。

这样,直到最后得到int类型的-1,程序结束。

第一次回帖,希望可以得到技术分啊,我想已经够详细了吧。
谢谢。
作者: 彭润生    时间: 2012-9-4 21:54
因为你自己实现的是和BufferedInputStream相同的一个类,而BufferedInputStream中的其read方法返回的就是int,所以就得用int。不知道能不能解决你的疑问。
作者: 黑马-李勇    时间: 2012-9-4 22:44
byte在循环读数时可能会从中读出来一个-1(1111  1111),但这个数不是文件结尾退出的那个-1.为了避免在中途就退出,所以在中间将数据提升,写入时再将数据强制转换成byte写入文件。这样做只是为了避免数据中间出错。




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