2010-10-13 2 views
1

Это код, который отлично работает на Mac OS (JDK 1.6):Что не так с моим механизмом сериализации?

String s1 = "test"; 
ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes()); 
String s2 = (String)(new ObjectInputStream(in).readObject()); 

В Linux CentOS 5.4 Java говорит:

java.io.StreamCorruptedException: invalid stream header: 3F3F0005 
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783) 
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280) 
at com.XXX.SerializableTest.testWorks(SerializableTest.java:26) 
[...] 

Что это?

ответ

12

ObjectInputStream работает только с данными, написанными ObjectOutputStream.

Метод getBytes()String не является механизмом сериализации Java; он просто кодирует строку символов, используя кодировку символов по умолчанию для вашей платформы.


Использование метода без аргументов getBytes() это плохая идея для большинства приложений. Как я уже сказал, он использует кодировку по умолчанию для платформы, на которой он работает. Если результат будет использоваться на другой машине, он, скорее всего, сломается.

Для большинства приложений вы должны явно указать кодировку символов, которая будет использоваться.

Важно помнить, что некоторые последовательности байтов недействительны в некоторых кодировках символов. Если вы хотите преобразовать произвольную последовательность байтов в строку символов, выберите кодировку, которая присваивает один символ каждому байтовому значению (если есть такая вещь, общие, с которыми я знаком, не используют каждый байт) ,

Я предполагаю, что вместо "test", строка в вопросе была создана что-то вроде этого:

ByteArrayOutputStream buf = ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(buf); 
oos.writeObject(x); 
oos.flush(); 
oos.close(); 
/* BAD! you should specify encoding! */ 
String encoded = new String(buf.toByteArray()); 

Вместо этого, последняя строка должна выглядеть следующим образом, где encoding является подходящей кодировки символов, а обсуждалось выше:

String encoded = new String(buf.toByteArray(), encoding); 

Однако, гораздо лучше, метод будет использовать кодировку, который был специально разработан для представления «двоичный» данные в виде текста. Base-64 широко поддерживается. Base-85 является более компактным, но не столь распространенным. Вам понадобится сторонняя библиотека для использования одного из этих кодировок. (Base-64 реализован во время выполнения Sun [Oracle], но он не является частью общедоступного API.)

+0

Почему он работает на Mac OS и не работает в Linux? Я хочу подтвердить, что данные были правильно сериализованы каким-либо другим инструментом заранее. Таким образом, единственное, что у меня есть, это экземпляр «String», который появился из другого места. В этом фрагменте я должен де-сериализовать поток 'char'-s в объект. Как я могу это сделать? – yegor256

+0

@ Винченцо - Извините, но я не понимаю, что вы имеете в виду. Вы создаете свой собственный метод сериализации? Тогда не используйте 'ObjectInputStream'; это конкретный формат, так же, как вы не могли использовать декодер JPG для чтения нового формата файла изображения, который вы придумали сами. – erickson

+1

@ Vincenzo - Хорошо, прочитав ваши комментарии по другому ответу, я думаю, я мог бы понять. Действительно ли строка 's1' действительно' 'test" '? Или это какая-то нечитаемая тарабарщина? Если последний, пожалуйста, ознакомьтесь с обновлением моего ответа. – erickson

Смежные вопросы