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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 001可望成功 中级黑马   /  2014-6-26 18:58  /  1422 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 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型。大体上就是这个意思,想了好长时间才明白的。

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

6 个回复

倒序浏览
剖出异常那块有点乱了
回复 使用道具 举报
分析的很好,学习了,以前只知其然,现在知其所以然了。
回复 使用道具 举报
乱的很。。。
回复 使用道具 举报
是有点乱了,但这一块在学IO的时候郁闷了很长时间,写出来希望大家可以互相学习
回复 使用道具 举报
表示看不懂。要继续学习了。。。
回复 使用道具 举报
钟翠翠 发表于 2014-6-28 11:24
表示看不懂。要继续学习了。。。

就是read()方法那得一点小问题,其中涉及到了一点计算机原理的东西
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马