ObjectInputStream доволен FileInputStream, недоволен getResourceAsStream - PullRequest
14 голосов
/ 24 марта 2011

У меня есть довольно стандартный код, который принимает сериализованный объект из потока, который выглядит примерно так:

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

Ответы [ 5 ]

18 голосов
/ 24 марта 2011

EFBFBD - это представление UTF-8 символа замены Unicode U + FFFD.Таким образом, похоже, что файл был передан через какой-то процесс преобразования кодировки.

Maven может быть подозрительным, особенно его функция фильтрации ресурсов.

7 голосов
/ 21 мая 2012

В вашем случае это был 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, так что, возможно, некоторые из этих шагов не нужны, но они сработали для меня.

6 голосов
/ 27 ноября 2013

Этот работал для меня.

        <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 голос
/ 08 мая 2013

Одна из проблем заключается в том, что maven пытается отфильтровать все в папке ресурсов.Создайте отдельную папку и затем попросите maven не фильтровать ее.

<resources>
   <resource>
       <directory>${basedir}/bin</directory>
       <filtering>false</filtering>
       <includes>
           <include>**/*</include>
       </includes>
   </resource>
</resources>
0 голосов
/ 24 марта 2011

Не должно быть никакой разницы - путь, который вы используете для getResourceAsStream (), должен найти какой-то другой файл.Выполните поиск других файлов, сохраненных как serializedObjects / testObject, и посмотрите, не можете ли вы их найти.Помните, что FileInputStream будет выглядеть относительно текущего каталога, а getResourceAsStream () - относительно пути к классу.

...