关于java字节流的read()方法返回int型而非byte型的思考
来源:互联网 发布:mysql的case语句 编辑:程序博客网 时间:2024/05/16 19:28
我们都知道java中io操作分为字节流和字符流,对于字节流,顾名思义是按字节的方式读取数据,所以我们常用字节流来读取二进制流(如图片,音乐等文件)。问题是为什么字节流中定义的read()方法返回值为int类型呢?既然它一次读出一个字节数据为什么不返回byte类型呢?(不知道有没有人和我有同样的困惑,不过既然有了问题咱就得解决。)
于是我翻阅了java的源码,下面先把源码贴出来(以BufferedInputStream/BufferedOutputStream为例):
//BufferedInputStream中的read()方法的实现
/** * See * the general contract of the <code>read</code> * method of <code>InputStream</code>. * * @return the next byte of data, or <code>-1</code> if the end of the * stream is reached. * @exception IOException if this input stream has been closed by * invoking its {@link #close()} method, * or an I/O error occurs. * @see java.io.FilterInputStream#in */ public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff;//这边getBufIfOpen()返回的是byte[],而& 0xff是为了保证由char类型向上拓展成int的时候,不进行符号拓展,而是0拓展。}
从源码中我们得到的信息是直到getBufIfOpen()方法返回,我们得到的都是byte类型,可是为什么方法的最终返回值是int?
首先我先简单解释下符号扩展,这是指由byte向上转化成更宽的类型时,是扩展的符号位。这对于正数补0,负数补1,例如,定义byte b = -1;在计算机内部它是用八位1111 1111表示的,当扩展成32位整型的时候,一般情况下是1111 1111 1111 1111 1111 1111 1111 1111,即符号扩展,而对于无符号扩展,也称为0扩展,其结果是0000 0000 0000 0000 0000 0000 1111 1111(实际上这样一来值已经变成255了)。过于向上转型和强制向下转型的进一步讨论,我在以后再说。这里要说的是我们能从java源码中得到的第二个信息,即上面的注释部分,read()方法的最后一行把读到的字节0扩展成了int,也就是说如果我们直接读出来这个值可能就是不对了。这里我又疑惑了,为什么BufferedOutputStream中的writer()方法能正确读出字节呢?所以我再去查下对应的源码:
public synchronized void write(int b) throws IOException { if (count >= buf.length) { flushBuffer(); } buf[count++] = (byte)b; }
可以看到,这里它果断的又将int强制转成了byte(截取后八位)。于是总结下现在得到的信息是,java字节流把byte转成int读出来再转回byte存起来。何必呢?
经过一番思考,我初步有了答案:在用输入流读取一个byte数据时,有时会出现连续8个1的情况,这个值在计算机内部表示-1,正好符合了流结束标记。所以为了避免流操作数据提前结束,将读到的字节进行int类型的扩展。保留该字节数据的同时,前面都补0,避免出现-1的情况。而真正读到文件最后结束是通过这句实现的:
if (pos >= count) return -1;
所以我们使用的-1这个结束标志是通过这句返回的,而不是输入流读到了一个-1。
这样一来就解决了我们前面的疑惑,也证实了确实有这样实现的必要。对于字符流的读写也可以用类似的方法分析,这里不再赘述。
当然了java的设计者有可能还有许多其他各方面的考虑,如果大家有不同见解请提出来让我学习下。此博文仅供参考。
- 关于java字节流的read()方法返回int型而非byte型的思考
- 关于java字节流的read()方法返回int型而非byte型的思考
- 关于java字节流的read()方法返回值为int的思考
- 为什么Java的InputStream.read函数要返回int型而实际上它只读一个byte
- java基础--Java 字节读取流的read方法返回int的原因
- java基础--Java 字节读取流的read方法返回int的原因
- 为什么read()方法返回的是int类型而不是byte
- 为什么IO读取流的read方法返回的是int而不是byte的原因!
- (转)为什么IO读取流的read方法返回的是int而不是byte的原因!
- Java中字节流和字符流的read()方法为什么返回的值是int类型
- Java中字节流和字符流的read()方法为什么返回的值是int类型
- Java中字节流和字符流的read()方法为什么返回的值是int类型
- IO流里的 read(),read(byte[]),read(byte[],int off,int len)以及write
- java.io.FileInputStream.read()的返回值类型为什么是int而不是byte
- Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值
- Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值
- Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值
- java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值
- linux下的mtd
- 异步任务
- Hibernate继承映射学习
- 产品研发注意事项,对产品经理说的几句话
- ubuntu中安装deb、bin、rpm、及源程序文件
- 关于java字节流的read()方法返回int型而非byte型的思考
- c++面向对象编程必备“良方”(欢迎大家来补充!) .
- 不管你是学生、程序开发员、设计师还是办公室职员,这几个工具都十分有用。一起来看看都有哪些。
- JAVA获取/删除文件夹及文件夹下所有文件
- RFC2326 - Real Time Streaming Protocol (RTSP) 完整中英文对照版
- Android linux adb安装操作命令图解
- dll生成对应的导入库lib
- u-boot-2011.06的改变--开发板配置
- Vous êtes en Afrique