14

我有一些非常标准的代码,它从流中接收序列化对象,基本上看起来像这样:

  对象 getObjectFromStream(InputStream is) {
    ObjectInputStream ois = new ObjectInputStream(is);
    返回ois.readObject();
  }

然后我的资源文件夹中有一个文件,所以在我的开发机器上,我可以将它作为文件引用,也可以作为 JarResource 引用:

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

在我看来,两者都应该做同样的事情。然而,碰巧的是,两者都解析为有效(非空)流,但 FileInputStream 从我的 getObjectFromStream(InputStream) 方法正确返回了一个 Object,而 getResourceAsStream 版本抛出此异常:

  java.io.StreamCorruptedException:无效的流标头:EFBFBDEF
    在 java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:800)
    在 java.io.ObjectInputStream.(ObjectInputStream.java:297)

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

4

5 回答 5

18

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

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

于 2011-03-24T15:59:50.377 回答
7

在您的情况下,是 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 的专家,所以可能不需要其中一些步骤,但它们对我有用。

于 2012-05-21T14:00:17.043 回答
6

这个对我有用。

        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>2.5</version>
          <configuration>
            <encoding>UTF-8</encoding>
            <nonFilteredFileExtensions>
              <nonFilteredFileExtension>xls</nonFilteredFileExtension>
              <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
              <nonFilteredFileExtension>jrxml</nonFilteredFileExtension>
              <nonFilteredFileExtension>jasper</nonFilteredFileExtension>
            </nonFilteredFileExtensions>
          </configuration>
        </plugin>
于 2013-11-27T17:27:35.313 回答
1

一个问题是 Maven 试图过滤资源文件夹中的所有内容。制作一个单独的文件夹,然后指示maven不要过滤它。

<resources>
   <resource>
       <directory>${basedir}/bin</directory>
       <filtering>false</filtering>
       <includes>
           <include>**/*</include>
       </includes>
   </resource>
</resources>
于 2013-05-08T18:25:27.873 回答
0

应该完全没有区别——您用于 getResourceAsStream() 的路径必须找到其他文件。搜索存储为 serializedObjects/testObject 的其他文件,看看是否找不到。请记住,FileInputStream 是相对于当前目录的,而 getResourceAsStream() 是相对于类路径的。

于 2011-03-24T15:56:52.960 回答