Это довольно распространенное явление, когда StreamCorruptedException генерируется с «причиной», которая заявляет « недопустимый заголовок потока », а затем предоставляет первую часть этого недопустимого заголовка потока. Часто полезной подсказкой для определения причины этого исключения является понимание того, что является недопустимым заголовком потока, потому что это объясняет, что является неожиданным и вызывает проблему.
StreamCorruptedException имеет только два конструктора, один из которых не принимает аргументов, а другой принимает одну строку, описывающую «причину» исключения. Это говорит нам о том, что сообщения «недопустимый заголовок потока: XXXXXXXX» (где XXXXXXXX представляет различные сведения о недопустимом заголовке) предоставляются кодом, который создает (и предположительно StreamCorruptedException
) эти StreamCorruptedException
а не самим этим классом исключений. Это означает, что это не всегда будет одно и то же отформатированное сообщение, встречающееся с одним из этих исключений, но в большинстве распространенных случаев формат совпадает с «недопустимым заголовком потока:», за которым следует первая часть этого недопустимого заголовка потока.
Это исключение обычно выдается ObjectInputStream . Javadoc для этого класса содержит некоторые полезные детали, которые помогают объяснить, почему встречается « StreamCorruptedException: неверный заголовок потока ». Javadoc уровня класса утверждает: «Только потоки, которые поддерживают интерфейс java.io.Serializable или java.io.Externalizable, могут быть прочитаны из потоков». Javadoc для конструктора ObjectInputStream (InputStream) утверждает (я добавил акцент ): «Создает ObjectInputStream, который читает из указанного InputStream . Заголовок потока сериализации читается из потока и проверяется ».
Как объясняет цитируемый Javadoc, ObjectInputStream
следует использовать с сериализованными данными. Многие случаи сообщения «StreamCorruptedException: недопустимый заголовок потока» возникают, когда текстовый файл (например, HTML, XML, JSON и т. Д.) Передается в этот конструктор, а не в сериализованный файл Java.
Ниже приведены примеры значений «ASCII», полученных из сообщений «неверный заголовок потока», связанных с StreamCorruptedException
и сообщаемых в режиме онлайн.
Приведенные выше примеры показывают сообщение «StreamCorruptedException: неверный заголовок потока», возникающее в случаях, когда входные потоки, представляющие текст, были переданы в конструктор, который ожидает сериализованный формат Java. Выделенный ряд особенно интересен. Эта запись (« ACED » в символьном представлении «ASCII») выглядит так, как ожидается во всех файлах, сериализованных сериализацией Java по умолчанию , но она не совсем корректна.
Раздел « Терминальные символы и константы » Спецификации Сериализации Объекта Java говорит нам, что java.io.ObjectStreamConstants определяет константу STREAM_MAGIC, которая является «Магическим числом, которое записывается в заголовок потока». В спецификации также объясняется, что ObjectStreamConstants.STREAM_MAGIC
определен как (short)0xaced
и это может быть проверено в коде Java, если это необходимо. Причина того, что конкретная запись привела к ошибке, состоит в том, что это должно быть шестнадцатеричное представление, которое является «ACED», а не переведенным представлением «ASCII». Другими словами, для этого конкретного случая это был буквальный текст «ACED», который был в первых байтах, а не байты, представленные шестнадцатеричным представлением «ACED».
Существует много способов перевести шестнадцатеричное представление, представленное в сообщении «StreamCorruptedException: недопустимый заголовок потока», чтобы посмотреть, преобразуется ли оно в текст, который что-то значит. Если это текст, он знает, что он или она плохо начал, поскольку вместо текста следует использовать двоичный сериализованный файл. Символы в этом тексте могут дать дополнительную подсказку о том, какой тип текстового файла был предоставлен случайно. Вот один из способов перевода предоставленного шестнадцатеричного представления в текст «ASCII» с использованием Java ( доступно на GitHub ):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
private static String toAscii( final String hexInput) { final int length = hexInput.length(); final StringBuilder ascii = new StringBuilder(); final StringBuilder integers = new StringBuilder(); for ( int i = 0 ; i < length; i+= 2 ) { final String twoDigitHex = hexInput.substring(i, i+ 2 ); final int integer = Integer.parseInt(twoDigitHex, 16 ); ascii.append(( char )integer); integers.append(String.format( "%03d" , integer)).append( " " ); } return hexInput + " ==> " + integers.deleteCharAt(integers.length()- 1 ).toString() + " ==> " + ascii.toString(); } |
Потоки текста, непреднамеренно переданные в конструктор ObjectInputStream
, не являются единственной причиной «StreamCorruptedException: неверный заголовок потока». Фактически, любой InputStream
(текстовый или двоичный), который не начинается с ожидаемых «магических потоков» байтов ( 0xaced
), приведет к этому исключению.
Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: Значение синтаксического анализа от StreamCorruptedException: неверный заголовок потока. Сообщение
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |