ObjectInputStream对FileInputStream感到满意,对getResourceAsStream不满意

我有一些非常标准的代码,它从流中接收序列化对象,其基本如下所示:

  Object getObjectFromStream(InputStream is) {
    ObjectInputStream ois = new ObjectInputStream(is);
    return ois.readObject();
  }

然后,我的资源文件夹中有一个文件,因此在我的开发计算机上,我可以将其作为文件或JarResource引用:

  InputStream is = new FileInputStream("/home/.../src/main/resources/serializedObjects/testObject");
  InputStream is = this.getClass().getResourceAsStream("/serializedObjects/testObject");

在我看来,两者都应该做同样的事情。但是,碰巧的是,两者都解析为有效(非空)流,但FileInputStream正确地从我的getObjectFromStream(InputStream)方法返回对象,而getResourceAsStream版本则引发此异常:

  java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:800)
    at java.io.ObjectInputStream.(ObjectInputStream.java:297)

大多数情况下,我想知道如何解决这个问题,但我也希望了解两个输入流之间的区别......


答案 1

EFBFBD是 Unicode 替换字符 U+FFFD 的 UTF-8 表示形式。因此,看起来文件是通过一些编码转换过程传递的。

Maven可能是一个嫌疑人,尤其是它的资源过滤功能。


答案 2

在你的情况下,是Maven弄乱了你的文件,但是我出于不同的原因发现了同样的事情,所以我在这里记录它,因为这是Google上唯一有用的搜索结果。

我将序列化对象保存为单元测试的数据集,并将它们存储在版本控制中。这是否是一个好主意还有待商榷,但又是另一个时间。

这些文件以以下格式开头:

AC ED 00 05 ...

将它们存储在 Git 中后,它们将变为:

EF BF BD EF BF BD 00 05 ...

这会导致错误:

java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:782)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)

Git 不仅更改了这些打开的字节,还更改了整个文件中的许多字节。它试图在Windows和Unix样式的行尾之间进行转换。用于标识文件是否包含文本的启发式方法失败。

解决方案是添加一个文件,该文件指定了要从此处理中排除的一些文件:.gitattributes

*.bytes -crlf

我还确保我的文件具有以下内容:.git/config

[core]
    autocrlf = false

通过这些更改,我删除了索引并强制重置:

rm .git/index
git reset      # force rescan of the index
git status     # any files listed here will experience changes
git add -u
git commit -m "Line ending normalisation changes."

希望能帮助别人。我不是 Git 的大师,所以可能不需要其中一些步骤,但它们对我有用。


推荐