首页 文章

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");

在我的脑海中,两者都应该做同样的事情 . 然而,当它发生时,两者都解析为有效(非空)流,但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之间的区别......

5 回答

  • 18

    EFBFBD 是Unicode替换字符U FFFD的UTF-8表示 . 所以,看起来文件是通过一些编码转换过程传递的 .

    Maven可能是一个嫌疑人,特别是它的资源过滤功能 .

  • 1

    在你的情况下,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的大师,所以可能不需要其中一些步骤,但它们对我有用 .

  • 7

    这个对我有用 .

    <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>
    
  • 6

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

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

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

相关问题