157 votes

Comment sérialiser un objet dans une chaîne de caractères

Je suis en mesure de sérialiser un objet dans un fichier puis de le restaurer comme le montre l'extrait de code suivant. Je voudrais sérialiser l'objet dans une chaîne et le stocker dans une base de données. Quelqu'un peut-il m'aider ?

LinkedList<Diff_match_patch.Patch> patches = // whatever...
FileOutputStream fileStream = new FileOutputStream("foo.ser");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(patches1);
os.close();

FileInputStream fileInputStream = new FileInputStream("foo.ser");
ObjectInputStream oInputStream = new ObjectInputStream(fileInputStream);
Object one = oInputStream.readObject();
LinkedList<Diff_match_patch.Patch> patches3 = (LinkedList<Diff_match_patch.Patch>) one;
os.close();

280voto

OscarRyz Points 82553

Sergio :

Vous devez utiliser BLOB . C'est assez simple avec JDBC.

Le problème avec le deuxième code que vous avez posté est l'encodage. Vous devriez coder les octets en plus pour vous assurer qu'aucun d'entre eux n'échoue.

Si vous voulez toujours l'écrire dans une chaîne de caractères, vous pouvez coder les octets à l'aide de la fonction java.util.Base64 .

Vous devez tout de même utiliser CLOB comme type de données car vous ne savez pas quelle sera la longueur des données sérialisées.

Voici un exemple de la façon de l'utiliser.

import java.util.*;
import java.io.*;

/** 
 * Usage sample serializing SomeClass instance 
 */
public class ToStringSample {

    public static void main( String [] args )  throws IOException,
                                                      ClassNotFoundException {
        String string = toString( new SomeClass() );
        System.out.println(" Encoded serialized version " );
        System.out.println( string );
        SomeClass some = ( SomeClass ) fromString( string );
        System.out.println( "\n\nReconstituted object");
        System.out.println( some );

    }

    /** Read the object from Base64 string. */
   private static Object fromString( String s ) throws IOException ,
                                                       ClassNotFoundException {
        byte [] data = Base64.getDecoder().decode( s );
        ObjectInputStream ois = new ObjectInputStream( 
                                        new ByteArrayInputStream(  data ) );
        Object o  = ois.readObject();
        ois.close();
        return o;
   }

    /** Write the object to a Base64 string. */
    private static String toString( Serializable o ) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream( baos );
        oos.writeObject( o );
        oos.close();
        return Base64.getEncoder().encodeToString(baos.toByteArray()); 
    }
}

/** Test subject. A very simple class. */ 
class SomeClass implements Serializable {

    private final static long serialVersionUID = 1; // See Nick's comment below

    int i    = Integer.MAX_VALUE;
    String s = "ABCDEFGHIJKLMNOP";
    Double d = new Double( -1.0 );
    public String toString(){
        return  "SomeClass instance says: Don't worry, " 
              + "I'm healthy. Look, my data is i = " + i  
              + ", s = " + s + ", d = " + d;
    }
}

Sortie :

C:\samples>javac *.java

C:\samples>java ToStringSample
Encoded serialized version
rO0ABXNyAAlTb21lQ2xhc3MAAAAAAAAAAQIAA0kAAWlMAAFkdAASTGphdmEvbGFuZy9Eb3VibGU7T
AABc3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwf////3NyABBqYXZhLmxhbmcuRG91YmxlgLPCSilr+w
QCAAFEAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cL/wAAAAAAAAdAAQQUJ
DREVGR0hJSktMTU5PUA==

Reconstituted object
SomeClass instance says: Don't worry, I'm healthy. Look, my data is i = 2147483647, s = ABCDEFGHIJKLMNOP, d = -1.0

NOTE : pour Java 7 et les versions antérieures, vous pouvez voir l'original répondre ici

0 votes

+1 si vous avez VRAIMENT besoin de chaînes de caractères, alors base64+clob est la solution.

6 votes

+1, Petite amélioration. Il est préférable d'utiliser l'interface Serializable au lieu d'un simple Object dans la méthode toString() : private static String toString(Serializable object)

4 votes

Si nous essayons de stocker l'objet comme un tableau d'octets au lieu d'une chaîne de caractères, nous pouvons obtenir la même chose sans utiliser BASE64.

12voto

Outlaw Programmer Points 6610

Pourquoi ne pas écrire les données dans un ByteArrayOutputStream au lieu d'un FileOutputStream ?

Sinon, vous pourriez sérialiser l'objet à l'aide de XMLEncoder, persister le XML, puis désérialiser via XMLDecoder.

8voto

Sergio del Amo Points 14991

Merci pour ces réponses rapides et efficaces. Je vais donner quelques votes positifs immédiatement pour reconnaître votre aide. J'ai codé la meilleure solution à mon avis sur la base de vos réponses.

LinkedList<Patch> patches1 = diff.patch_make(text2, text1);
try {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(bos);
    os.writeObject(patches1);
    String serialized_patches1 = bos.toString();
    os.close();

    ByteArrayInputStream bis = new ByteArrayInputStream(serialized_patches1.getBytes());
    ObjectInputStream oInputStream = new ObjectInputStream(bis);
    LinkedList<Patch> restored_patches1 = (LinkedList<Patch>) oInputStream.readObject();            

        // patches1 equals restored_patches1
    oInputStream.close();
} catch(Exception ex) {
    ex.printStackTrace();
}

Note Je n'ai pas envisagé d'utiliser JSON car c'est moins efficace.

Note : Je vais prendre en compte votre conseil de ne pas stocker les objets sérialisés sous forme de chaînes dans la base de données mais plutôt sous forme de byte[].

3 votes

" ByteArrayOutputStream.toString " convertit en utilisant la fonction encodage par défaut de la plate-forme . Êtes-vous sûr de vouloir cela ? D'autant plus qu'un tableau d'octets arbitraire n'est pas un UTF8 valide. De plus, la base de données va le malmener."

0 votes

Vous devriez prendre au sérieux le commentaire de Tom Hawtin ci-dessus.

0 votes

Sans compter que le stockage à long terme d'objets sérialisés n'est pas une bonne idée et n'est pas recommandé.

4voto

Kristian Points 2163

Que diriez-vous de persister l'objet comme un blob

0 votes

Corrige le lien, ok ?

3voto

Daniel Spiewak Points 30706

Si vous stockez un objet sous forme de données binaires dans la base de données, vous devriez vraiment utiliser une balise BLOB type de données. La base de données est en mesure de le stocker plus efficacement, et vous n'avez pas à vous soucier des encodages et autres. JDBC fournit des méthodes pour créer et récupérer des blobs en termes de flux. Utilisez Java 6 si vous le pouvez, il a apporté quelques ajouts à l'API JDBC qui facilitent grandement la gestion des blobs.

Si vous avez absolument besoin de stocker les données sous forme de String, je vous recommande XStream pour le stockage basé sur XML (beaucoup plus facile que XMLEncoder ), mais d'autres représentations d'objets peuvent être tout aussi utiles (par exemple, JSON). Votre approche dépend de la raison pour laquelle vous avez réellement besoin de stocker l'objet de cette manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X