您的位置:首页 > 编程语言 > Java开发

Java 从流中读取byte的奇怪现象,出现负值,详解

2016-03-15 17:13 274 查看

其实一点都不奇怪,下面我们来详细分析

首先看下面一段代码,代码的意思是将128写入到文件中,再从文件中读出一个byte输出

File f = new File("f1");
FileOutputStream fos = new FileOutputStream(f);
fos.write(128);
fos.close();

FileInputStream fis = new FileInputStream(f);
int a = fis.read();
System.out.println(a);


输出结果为:

128

这符合我们的直观感觉,写入128,读出来也是128

下面我们修改一下代码,将数据度入到byte数组里,看看输出会是什么样子,代码如下

File f = new File("f1");
FileOutputStream fos = new FileOutputStream(f);
fos.write(128);
fos.close();

FileInputStream fis = new FileInputStream(f);
byte[] b = new byte[1];
fis.read(b, 0, 1);
System.out.println(b[0]);


输出结果为

-128

好了,“奇怪”的现象出现了,这是为什么呢?

首先,我们需要了解一些基础知识,在Java中,byte的范围为 -128 ~ 127,并没有128这个数值;其次,读者需要了解一下负数在Java中如何表示(即原码、反码、补码的相关知识,请读者自行谷歌)。

下面,我们来分析一下出现
-128
的原因:

首先,
fos.write(128)
表示写入 “128” 所代表的字节,即
1000 0000
,也就是说,文件中当前包含一个字节,8位依次为 1 0 0 0 0 0 0 0

当我们调用
fis.read()
时,该方法会返回一个无符号byte,也就说直接将
1000 0000
翻译为128,大家可以去看该方法的说明,返回值的范围为0 ~ 255;所以我们得到了 128 的输出;

当我们调用
fis.read(b, 0, 1)
时,相当于把文件中第一个字节读入到了b[0]中,此时b[0]的二进制表示为
1000 0000
,根据负数在Java中的表示方法,我们可以计算出,该二进制序列的数值为 -128,也就是说这个过程并没有将其转化为无符号数值的过程,所以我们得到了 -128 的输出。

那么,我们如何解决这个问题呢?

首先,我们需要看一下
fos.write(int a)
这个方法,它的功能是写入a代表的byte值,也就是说,该函数实际上是将a 的后八位写入到文件中 , 所以作者建议在使用该方法时,为了避免产生歧义,a 的范围最好在 0 ~ 255 之间,初学者最好在 0 ~ 127 之间。(具体原因可以结合负数的表示规则自己想想哦~)。

回归正题,我们如何解决上文中的问题呢,即 “写入128、读出-128” 的问题,我们可以用下面的代码来解决。

File f = new File("f1");
FileOutputStream fos = new FileOutputStream(f);
fos.write(128);
fos.close();

FileInputStream fis = new FileInputStream(f);
byte[] b = new byte[1];
fis.read(b, 0, 1);
System.out.println(b[0] & 0xff);


也就是说,用
b[0] & 0xff
的方法得到b[0]的无符号值。

插入一个小问题,就是,
b[0] | 0xff
得到的是一个负值,而 & 得到的却是一个正值。这里根据作者的猜测,可能是如下原因,主要和 & 运算的步骤有关:

进行
b[0] & 0xff
运算时的步骤如下:

因为0xff默认应该用int来保存,所以首先将 b[0] 强制转化为 int 类型表示,b[0] 的数值为-128,所以其二进制表示为11111111 11111111 11111111 10000000

0xff的二进制表示为 00000000 00000000 00000000 11111111

这两个数做 & 运算后,得到 00000000 00000000 00000000 10000000,其表示的值为128

“或 运算”的过程类似,读者可以自己推理一下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: