【问题标题】:ObjectInputStream happy with FileInputStream, not happy with getResourceAsStreamObjectInputStream 对 FileInputStream 满意,对 getResourceAsStream 不满意
【发布时间】:2011-07-22 06:26:31
【问题描述】:

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

对象 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) 方法返回一个对象,而 getResourceAsStream 版本抛出此异常:

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

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

【问题讨论】:

  • 我建议您更改文件名以检查它在两种情况下都在读取同一个文件。完成后不要忘记关闭流。 ;)
  • 你在用蚂蚁吗?查看this post

标签: java inputstream fileinputstream objectinputstream


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我确实在使用Maven的资源过滤系统。我会看看我是否可以为这些文件禁用它...
    • 是的 - 这绝对是问题所在,删除了过滤,它工作了,现在只需要弄清楚选择性过滤,但我 90% 在那里。谢谢。
    • Git 也为我处理了一些文件。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        这个对我有用。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多