开发者

ObjectInputStream happy with FileInputStream, not happy with getResourceAsStream

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开发者_如何学C also appreciate an understanding of the difference between the two InputStreams ...


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.


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.


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>


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>


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜