黑马程序员技术交流社区

标题: 流操作中的小知识大学问 [打印本页]

作者: 001可望成功    时间: 2014-6-26 18:58
标题: 流操作中的小知识大学问
本帖最后由 001可望成功 于 2014-7-13 10:55 编辑

  前几天提了一个问题是:java中流操作的-1问题?但是大家伙都说我好像有点专牛角尖了,这不是java要研究的问题。

  今天看见一位小伙伴提了一个类似的问题:“既然字节流的操作是按照字节进行读取的,那么每一次read能读取几个字节的长度呢
它定义的read方法返回的是int型,那么也就是说一次读取4个字节?  要是只读取一个字节那么用int型接收岂不是浪费了3byte的空间么
”。好多小伙伴的回复都表示没有注意到这个问题,所以专门发表这篇帖子,希望能和大家互相交流一下,如果有什么不对的地方,还望大家多多指教。

查看API文档可以知道:read方法一次读取数据的一个字节
public abstract int read()                  throws Exception
从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。public abstract void write(int b)                   throws Exception
将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。
  既然java是以字节的方式读取出来,然后又以字节的方式存了起来,那为什么中间要将byte类型向上转型为int呢,这样岂不是多此一举吗?
既然詹姆斯·高斯林能编写出java,就应该不会犯这样的错误。那问题就在read方法这了,read方法读到流末尾的时候,返回-1,问题是不是出在这呢,字节都是由0和1组成的,而-1的二进制表示是1000 0001,在计算机内存中表示是1111 1111(用的是补码),流在读取字节的时候,很容易出现1111 1111这种情况,这样就会返回一个“-1”的字节(前提是byte有符号位,无符号位的时候8个1是255),如果read方法和write方法都直接操作byte,那么这时流操作以为读到了结尾,就会结束读取,后面的数据也就丢失了。为了避免这种情况的出现,将byte向上转型为int,正数在前面补24个0,负数在前面补24个1,例如byte型-1,转为int后是32个1,但这32个1转为十进制后任然是-1啊,也没有起到效果啊。后来,在Java源码ByteArrayInputStream.java中终于找到了证据:
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }

将每一个独到的字节与0xff(十进制是255(16平方-1,因为最小的是0),二进制是00000000  00000000  00000000  11111111)按位与,将-1转换为255,这样只有当pos=count(即当前数=buf数组长度的时候)才返回-1。很好的解决了这个问题

而write方法存储的时候,只写最低八位,24个高位都将被忽略。这样又将int型存储为了byte型。大体上就是这个意思,想了好长时间才明白的。


作者: 001可望成功    时间: 2014-6-27 09:03
剖出异常那块有点乱了
作者: luheqi    时间: 2014-6-27 10:10
分析的很好,学习了,以前只知其然,现在知其所以然了。
作者: itisdream    时间: 2014-6-27 11:06
乱的很。。。
作者: 001可望成功    时间: 2014-6-28 11:05
是有点乱了,但这一块在学IO的时候郁闷了很长时间,写出来希望大家可以互相学习
作者: 钟翠翠    时间: 2014-6-28 11:24
表示看不懂。要继续学习了。。。
作者: 001可望成功    时间: 2014-6-28 12:25
钟翠翠 发表于 2014-6-28 11:24
表示看不懂。要继续学习了。。。

就是read()方法那得一点小问题,其中涉及到了一点计算机原理的东西




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