关于java字节流的read()方法返回值为int的思考
我们都知道java中io操作分为字节流和字符流,对于字节流,顾名思义是按字节的方式读取数据,所以我们常用字节流来读取二进制流(如图片,音乐 等文件)。问题是为什么字节流中定义的read()方法返回值为int类型呢?既然它一次读出一个字节数据为什么不返回byte类型呢?(不知道有没有人 和我有同样的困惑,不过既然有了问题咱就得解决。)
于是我翻阅了java的源码,下面先把源码贴出来(以BufferedInputStream/BufferedOutputStream为例):
//BufferedInputStream中的read()方法的实现
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的情况。而真 正读到文件最后结束是通过这句实现的:
[java] view plaincopy
if (pos >= count) return -1;
[java] view plaincopy
if (pos >= count) return -1;
所以我们使用的-1这个结束标志是通过这句返回的,而不是输入流读到了一个-1。
这样一来就解决了我们前面的疑惑,也证实了确实有这样实现的必要。对于字符流的读写也可以用类似的方法分析,这里不再赘述。
关于java字节流的read()方法返回值为int的思考的更多相关文章
- java 内存分析之方法返回值二
package Demo; class Point { private double x, y; public Point(double x, double y) { this.x = x; this ...
- java 内存分析之方法返回值及匿名对象一
package Demo; public class Point { private double x, y, z; public Point(double _x, double _y, double ...
- 慕课网-Java入门第一季-7-3 Java 中无参带返回值方法的使用
来源:http://www.imooc.com/code/1579 如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值 ...
- Java 中无参带返回值方法的使用
如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果 在 c ...
- java 反射获取方法返回值类型
//ProceedingJoinPoint pjp //获取方法返回值类型 Object[] args = pjp.getArgs(); Class<?>[] paramsCls = ne ...
- SpringMVC第五篇【方法返回值、数据回显、idea下配置虚拟目录、文件上传】
Controller方法返回值 Controller方法的返回值其实就几种类型,我们来总结一下-. void String ModelAndView redirect重定向 forward转发 数据回 ...
- JAVAEE——SpringMVC第二天:高级参数绑定、@RequestMapping、方法返回值、异常处理、图片上传、Json交互、实现RESTful、拦截器
1. 课前回顾 https://www.cnblogs.com/xieyupeng/p/9093661.html 2. 课程计划 1.高级参数绑定 a) 数组类型的参数绑定 b) List类型的绑定 ...
- Java的Object.hashCode()的返回值到底是不是对象内存地址?
关于这个问题,查阅了网上的资料,发现证明过程太繁琐,这里我用了反证法. java.lang.Object.hashCode()的返回值到底是不是对象内存地址? hashCode契约 说到这个问题,大家 ...
- C# 方法返回值的个数
方法返回值类型总的来说分为值类型,引用类型,Void 有些方法显示的标出返回值 public int Add(int a,int b) { return a+b; } 有些方法隐式的返回返回值,我们可 ...
随机推荐
- 中英文代码对比系列之Java一例
原文: https://zhuanlan.zhihu.com/p/30905033. 作者为本人. 这个系列将对同一段代码进行中文命名和英文命名两个版本的比较. 目的包括, 演示中文命名, 发现命名时 ...
- JavaScript:彻底理解同步、异步和事件循环(Event Loop)
一. 单线程 我们常说"JavaScript是单线程的". 所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个.不妨叫它主线程. 但是实际上还存在其他 ...
- Spring Cloud Feign 整合 Hystrix
在前面随笔Spring Cloud 之 Feign的feign工程基础上进行改造 1.pom.xml依赖不变 2.application.yml文件添加feign.hystrix.enabled=tr ...
- POJ3624--01背包
Charm Bracelet Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 34013 Accepted: 15087 ...
- 实现快餐配送页面jq
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>快 ...
- 【ASP.NET Core】运行原理[3]:认证
本节将分析Authentication 源代码参考.NET Core 2.0.0 HttpAbstractions Security 目录 认证 AddAuthentication IAuthenti ...
- vue.js介绍,常用指令,事件,以及制作简易留言版
一.vue是什么? 一个mvvm框架(库).和angular类似,比较容易上手.小巧,让我们的代码更加专注于业务逻辑,而不是去关注DOM操作 二.vue和angular之间的区别 vue--简单易学 ...
- tensorflow 自定义损失函数示例
这个自定义损失函数的背景:(一般回归用的损失函数是MSE, 但要看实际遇到的情况而有所改变) 我们现在想要做一个回归,来预估某个商品的销量,现在我们知道,一件商品的成本是1元,售价是10元. 如果我们 ...
- opensslBIO系列之2---BIO结构和BIO相关文件介绍
BIO结构和BIO相关文件介绍 (作者:DragonKing Mail:wzhah@263.net 公布于:http://gdwzh.126.com openssl专业论坛) ...
- Android用户登录机制安全性的一些思考
1 client要做到安全存贮数据非常难,通过反编译和强攻.仅仅要有心,差点儿都能够破解. 2 服务端相对安全. 3 结合以上两点,推出能做的点是控制灾难规模.每次破解一个client仅仅能针对 ...