【问题标题】:ByteArrayInputStream to ObjectInputStream disappearedByteArrayInputStream 到 ObjectInputStream 消失了
【发布时间】:2017-02-04 00:55:35
【问题描述】:

我有一些不明白的地方,请帮忙。

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. 然后我想我的字节可能是无效的,所以我把每个字节都打印出来了,你可以看到,这四个字节都是有效的。

所以,我不知道为什么会发生这种情况。

请帮忙,非常感谢!

【问题讨论】:

  • 输入数据是什么?在 4 个字节处,它似乎不太可能是一个对象。正如文档所说,An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.
  • 如何显示输入?我认为 Arrays.toString(buffer) 是我能展示的最好的。
  • 所以这是我之前评论中的问题:data and objects previously written using an ObjectOutputStream。你不这样做。您正在读取从未通过 ObjectInputStream 的原始字节。

标签: java io objectinputstream bytearrayinputstream


【解决方案1】:

正如提到的另一个答案,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,所以上面可能不是最佳实践或有多余的代码。)

【讨论】:

  • 感谢指出,绝对加深了我的理解! ^ ^
【解决方案2】:

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

返回可以在没有阻塞的情况下读取的字节数。

因此,它不会返回数组/读取中存在的bytes 的总数,而是返回在被阻止之前它可以读取的bytes 的数量。所以,它返回 0 是一个有效的场景。

现在,我们来看看ObjectInputStream的javadoc,下面是简要说明:

超过分配数据末尾的非对象读取将 以同样的方式反映数据的结尾 流结束:按字节读取将返回 -1 作为字节读取或 读取的字节数,原始读取将抛出 EOFExceptions。如果 没有对应的writeObject方法,则默认结束 序列化数据标志着分配数据的结束。

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

然后我尝试写/读一个新对象并测试available方法调用,看看下面的sn-p:

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 方法仍然返回 0。因此,我建议不要过分依赖 available,因为它的名称具有误导性:)

【讨论】:

    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 2012-06-23
    • 1970-01-01
    相关资源
    最近更新 更多