ByteArrayInputStream 到 ObjectInputStream 消失了

ByteArrayInputStream to ObjectInputStream disappeared

有不懂的地方,请大家帮忙

System.out.println("\n" + Arrays.toString(buffer) + "\n");
System.out.println("buffer.length = " + buffer.length + "\nnew ByteArrayInputStream(buffer).available() is: " + new ByteArrayInputStream(buffer).available());
ObjectInput input = new ObjectInputStream(new ByteArrayInputStream(buffer));
System.out.println("input.available(): " + input.available());

其输出如下:

[-84, -19, 0, 5]

buffer.length = 4
new ByteArrayInputStream(buffer).available() is: 4
input.available(): 0

我很困惑为什么一个4个有效字节的字节数组,在放入ObjectInputStream之后,它变成了零。

我尝试过的事情:

  1. 起初,我怀疑我的字节数组是空的,但正如你所见,我打印出来,它的长度是 4。
  2. 然后我想我的字节可能是无效的,所以我把每个字节都打印出来,你可以看到,这四个字节都是有效的。

所以,我不知道为什么会这样。

请帮忙,非常感谢!

Hereavailable 方法的 javadoc,它是这样写的:

Returns the number of bytes that can be read without blocking.

因此,它不会 return 您 array/read 中存在的 bytes 总数,它 return 是 bytes 它可以在被封锁之前阅读。所以,它 returning 0 是一个有效的场景。

现在,让我们看一下ObjectInputStream的javadoc,这里是简要说明:

Non-object reads which exceed the end of the allotted data will reflect the end of data in the same way that they would indicate the end of the stream: bytewise reads will return -1 as the byte read or number of bytes read, and primitive reads will throw EOFExceptions. If there is no corresponding writeObject method, then the end of default serialized data marks the end of the allotted data.

您在代码中尝试做的是 read 原始数据(或不使用 WriteObject 方法读取),因为它不是有效数据(对于 ObjectInputStreamread 将始终 return -1。我能够通过调用 readObject 方法重现 EOFException

然后我尝试 writing/reading 一个新对象并测试了 available 方法调用,看看下面的代码片段:

byte[] buffer = new byte[]{-84, -19, 0, 5};
System.out.println("\n" + Arrays.toString(buffer) + "\n");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer);
System.out.println("buffer.length = " + buffer.length + "\nnew ByteArrayInputStream(buffer).available() is: " + new ByteArrayInputStream(buffer).available());
ObjectInputStream input = new ObjectInputStream(byteArrayInputStream);
System.out.println("input.available(): " + input.available());
//      System.out.println(input.readObject()); //Uncomment to see EOFException

Date date = new Date();
System.out.println(date);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteArrayOut);
out.writeObject(date);
byte[] bytes = byteArrayOut.toByteArray();

input = new ObjectInputStream(new ByteArrayInputStream(bytes));
System.out.println(input.available());
System.out.println(input.readObject());

代码reads 已经写入的对象并打印值。请注意,即使它正确读取对象并打印相同的对象,available 方法仍然 returns 0。因此,我建议不要过分依赖 available 因为它是误导性名称:)

正如另一个答案提到的,available仅表示在发生阻塞之前您可以读取的字节数。

不过,我猜测您没有遵守 ObjectInputStream 的规则,其中指定 An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.

换句话说,为了用 ObjectInputStream 实际读取数据,您首先必须使用某种 ObjectOutputStream 写入数据。这是一个使用您提供的数据显示此内容的示例:

byte[] buffer = new byte[]{-84,-19,0,5};
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream= new ObjectOutputStream(out);
objectOutputStream.write(buffer);
objectOutputStream.flush();

ObjectInput input = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
System.out.println("input.available(): " + input.available());
System.out.println("input.readByte(): " + input.readByte());

(我要补充一点,我很少在 Java 中使用 IO,因此以上内容可能不是最佳实践或有多余的代码。)