ObjectInputStream 对 FileInputStream 满意,对 getResourceAsStream 不满意

发布于 2024-10-25 11:50:43 字数 883 浏览 6 评论 0原文

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

  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)

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

I have some pretty standard code which takes in a serialized object from a stream, which bascially looks like this:

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

I then have a file in my resources folder, so on my development machine, I can either reference it as a File, or as a JarResource:

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

In my head, both should do the exact same thing. As it happens however, both resolve to a valid (non-null) stream, but the FileInputStream correctly returns an Object from my getObjectFromStream(InputStream) method, while the getResourceAsStream version throws this exception:

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

Mostly, I would like to know how to fix this, but I'd also appreciate an understanding of the difference between the two InputStreams ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

嗳卜坏 2024-11-01 11:50:43

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

Maven 可能值得怀疑,尤其是它的资源过滤功能。

EFBFBD is a UTF-8 representation of Unicode replacement character U+FFFD. So, it looks like file was passed through some encoding conversion process.

Maven can be a suspect, especially its resource filtering feature.

旧人哭 2024-11-01 11:50:43

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

In your case it was Maven that was messing with your files, however I found the same thing for a different reason and so am documenting it here as this is the only useful search result on Google.

I was saving serialised objects as data sets for unit tests, and storing them in version control. Whether this was a good idea or not is up for debate, but another time.

The files started with:

AC ED 00 05 ...

After storing them in Git, they become:

EF BF BD EF BF BD 00 05 ...

This causes the error:

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

Git not only changes these opening bytes, but many bytes throughout the file. It's attempting to convert between Windows and Unix style line endings. The heuristic being used to identify whether the file contains text is failing.

The solution was to add a .gitattributes file that specified some files to exclude from this processing:

*.bytes -crlf

I also ensured my .git/config file has the following:

[core]
    autocrlf = false

With those changes, I deleted the index and forced a reset:

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

Hope that helps someone out. I'm not a guru of Git, so it may be that some of these steps are not needed, but they worked for me.

相权↑美人 2024-11-01 11:50:43

这对我有用。

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

This one worked for me.

        <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>
呆橘 2024-11-01 11:50:43

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

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

One issue is that maven tries to filter everything in the resource folder. Make a separate folder and then instruct maven not to filter it.

<resources>
   <resource>
       <directory>${basedir}/bin</directory>
       <filtering>false</filtering>
       <includes>
           <include>**/*</include>
       </includes>
   </resource>
</resources>
心舞飞扬 2024-11-01 11:50:43

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

There should be no difference at all -- the path you're using for getResourceAsStream() must be finding some other file. Do a search for other files stored as serializedObjects/testObject, and see if you can't find it. Remember that the FileInputStream is going to be looking relative to the current directory, while the getResourceAsStream() is relative to the class path.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文