2010-10-13 5 views
1

Ceci est le code qui fonctionne très bien sur Mac OS (JDK 1.6):Quel est le problème avec mon mécanisme de sérialisation?

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

sur CentOS Linux 5.4 Java dit:

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) 
[...] 

Qu'y at-il?

Répondre

12

ObjectInputStream ne fonctionne que sur les données écrites par ObjectOutputStream.

La méthode getBytes() de String n'est pas un mécanisme de sérialisation Java; il code simplement la chaîne de caractères en utilisant le codage de caractères par défaut pour votre plate-forme.


En utilisant la méthode getBytes() sans argument est une mauvaise idée pour la plupart des applications. Comme je l'ai indiqué, il utilise l'encodage par défaut pour la plate-forme sur laquelle il s'exécute. Si le résultat est utilisé sur une machine différente, il est susceptible de se casser.

Pour la plupart des applications, vous devez spécifier explicitement le codage de caractères à utiliser.

Il est important de garder à l'esprit que certaines séquences d'octets ne sont pas valides dans certains codages de caractères. Si vous voulez convertir une séquence arbitraire d'octets en une chaîne de caractères, choisissez un encodage qui attribue un seul caractère à chaque valeur d'octet (s'il y en a une, les communes que je connais n'utilisent pas tous les octets) .

Je devine que, au lieu de "test", la chaîne en question a été créé quelque chose comme ceci:

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()); 

Au lieu de cela, la dernière ligne devrait ressembler à ceci, où encoding est un codage de caractères approprié, comme discuté ci-dessus:

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

Cependant, bien meilleure technique serait d'utiliser un codage qui a été spécialement conçu pour représenter des données « binaires » sous forme de texte. Base-64 est largement pris en charge. Base-85 est plus compact, mais pas aussi répandu. Vous aurez besoin d'une bibliothèque tierce pour utiliser l'un de ces codages. (Base-64 est implémenté dans l'environnement d'exécution Sun [Oracle], mais il ne fait pas partie de l'API publique.)

+0

Pourquoi cela fonctionne-t-il sur Mac OS et ne fonctionne pas sous Linux? Je veux valider que les données ont été correctement sérialisées au préalable par un autre instrument. Ainsi, la seule chose que j'ai est une instance de 'String' qui vient d'un autre endroit. À cet extrait, je dois désérialiser un flux de 'char'-s dans un objet. Comment puis-je faire cela? – yegor256

+0

@Vincenzo - Je suis désolé, mais je ne comprends pas ce que vous voulez dire. Créez-vous votre propre technique de sérialisation? N'utilisez pas 'ObjectInputStream'; C'est un format spécifique comme si vous ne pouviez pas utiliser un décodeur JPG pour lire un nouveau format de fichier image que vous avez inventé. – erickson

+1

@Vincenzo - D'accord, en lisant vos commentaires sur l'autre réponse, je pense que je pourrais comprendre. La chaîne 's1' est-elle vraiment' 'test ''? Ou est-ce un charabia illisible? Si ce dernier, s'il vous plaît voir la mise à jour de ma réponse. – erickson

Questions connexes