【问题标题】:ByteArrayInputStream#read() strange behaviour for negative input bytesByteArrayInputStream#read() 负输入字节的奇怪行为
【发布时间】:2014-04-30 15:16:41
【问题描述】:

我在测试中遇到了这段代码。

byte[] bytes = new byte[] { -1, 1, 0x0 }; 
InputStream in = new ByteArrayInputStream(bytes); 
System.out.println(in.read() + in.read() + in.read());

我希望这段代码返回 0 (-1+1+0) 但它返回 256。

我很想知道。

谁能解释这种行为?

附言

显示第一条语句返回 255。为什么?

【问题讨论】:

  • 这是因为read()方法,将数据(每个1字节)读取为整数(4字节)
  • @parsa porahmad 你能详细介绍一下吗?
  • 根据java doc read() 方法读取下一个字节并将其作为整数返回。这意味着它在左边的实际值处添加了 3 个字节的空(nul)字节并返回它,所以 -1 将是 255,还不清楚吗?
  • 但是(对我来说)字节的负值不是预期的行为
  • 您可以使用DataInputStream 代替InputStream 类,它有一个方法readByte(),它读取一个字节并将其作为字节返回。

标签: java io byte bytearray inputstream


【解决方案1】:

InputStream#read

值字节以 0 到 255 范围内的 int 形式返回

尝试打印以下内容,您就会明白:

System.out.println(in.read());  //prints 255
System.out.println(in.read());  //prints 1
System.out.println(in.read());  //prints 0

所以 256 实际上是 255 + 1 + 0。

编辑:

read() 方法一次读取一个字节。在 Java 中,two's complement 中的 byte 以 8 位表示,如果您的 int 在 [128, 255] 范围内,则转换为 byte 将是 [-1, -128 ] 分别。

【讨论】:

  • 我不明白为什么第一个语句返回 255
  • 因为 -1 = 0xFF 并扩大到 int 0xFFFFFFFF。然后只取第一个字节 0xFFFFFFFF & 0xFF = 0x000000FF。这就是你得到 255 作为 int 的方式。
  • int 128 转换为字节 = -128。 int 255 转换为字节 = -1
【解决方案2】:

试试这段代码,你就会明白为什么了。

import java.io.ByteArrayInputStream;
import java.io.InputStream;


public class Test006 {

    public static void main(String[] args) throws Exception {
        byte[] bytes = new byte[] { -1, 1, 0x0 }; 
        InputStream in = new ByteArrayInputStream(bytes);
        System.out.println(in.read());
        System.out.println(in.read());
        System.out.println(in.read());
    }

}

第一个数字被读取为 int 255,因此总和为 256。

值 -1 看起来像这样一个字节。
1111 1111

显然,当它被读取为 int 时,Java 不会添加前导 1
(保留将其转换为 int -1 的符号)但添加​​
前导零。所以这个 int 变成了:

0000 0000 0000 0000 0000 0000 1111 1111

这是 int 255 而不是 -1。

int -1 看起来像这样:

1111 1111 1111 1111 1111 1111 1111 1111

所以...这就是 int 255 的来源。

【讨论】:

  • 第一个数字被读取为 int 255 这是问题点
  • 为什么是 int ?构造函数看起来像 public ByteArrayInputStream(byte buf[])...
  • 是的,但是 read 方法返回的是 int 而不是 byte。见这里:docs.oracle.com/javase/7/docs/api/java/io/…
  • 因此符号位表示为值位?
  • 是的,字节值 -n(对于区间 [1, 128] 中的每个 n)被读回为 int 值 256-n。这是这里的一般模式。尝试使用例如-1、-2、-5、-100、-127、-128。
猜你喜欢
  • 2023-04-07
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多