ObjectInputStream对FileInputStream很满意,但对getResourceAsStream不满意。

14
我有一些标准代码,可以从流中获取序列化的对象,大致如下:
  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");
在我的想法中,这两个应该做完全相同的事情。但是实际上,两者都会解析出有效(非 null)的流,但是FileInputStream会从getObjectFromStream(InputStream)方法中正确返回一个Object,而getResourceAsStream版本会抛出此异常:
  java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:800)
    at java.io.ObjectInputStream.(ObjectInputStream.java:297)
主要的问题在于如何解决这个问题,但我也希望了解两种InputStream之间的区别...

我建议您更改文件的名称以检查在两种情况下是否读取相同的文件。完成后不要忘记关闭流。 ;) - Peter Lawrey
你正在使用ant吗?请查看这篇文章 - Bala R
5个回答

18

EFBFBD 是 Unicode 替换字符 U+FFFD 的 UTF-8 表示方式。因此,看起来该文件经历了某种编码转换过程。

Maven 可能是罪犯,特别是其资源过滤功能可能存在问题。


我确实正在使用Maven的资源过滤系统。我会看看是否可以禁用它来处理那些文件... - barryred
4
@barryred: 请查看http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html末尾的警告。 - axtavt
没错 - 这绝对是问题所在,去掉了过滤,它就可以工作了,现在只需要解决选择性过滤的问题,但我已经完成了90%。谢谢。 - barryred
1
Git 也对我的一些文件做了这个。 - Drew Noakes

7
在你的情况下,是Maven在干扰你的文件,然而我因为另一个原因遇到了相同的问题,所以在这里记录下来,因为这是谷歌上唯一有用的搜索结果。
我将序列化对象保存为数据集用于单元测试,并将它们存储在版本控制中。这是一个好主意还是不好的主意还有待商榷,但这是另外一个话题。
这些文件以以下内容开头:
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的专家,因此可能有些步骤是不必要的,但它们对我起作用了。


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>

1

一个问题是maven尝试过滤资源文件夹中的所有内容。创建一个单独的文件夹,然后指示maven不要对其进行过滤。

<resources>
   <resource>
       <directory>${basedir}/bin</directory>
       <filtering>false</filtering>
       <includes>
           <include>**/*</include>
       </includes>
   </resource>
</resources>

0

完全不应该有任何区别——您在使用getResourceAsStream()时使用的路径必须找到其他文件。搜索存储为serializedObjects/testObject的其他文件,并查看是否可以找到它。请记住,FileInputStream将相对于当前目录进行查找,而getResourceAsStream()则相对于类路径进行查找。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接