Question

Je suis capable de sérialiser un objet dans un fichier, puis de le restaurer à nouveau, comme indiqué dans l'extrait de code suivant. Je voudrais sérialiser l'objet dans une chaîne et le stocker dans une base de données à la place. 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();
Était-ce utile?

La solution

Sergio:

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

Le problème avec le deuxième code que vous avez posté est le codage. Vous devez en outre coder les octets pour vous assurer qu'aucun d’entre eux n’échoue.

Si vous souhaitez toujours l'écrire dans une chaîne, vous pouvez coder les octets à l'aide de java.util.Base64 .

Vous devez toujours utiliser CLOB comme type de données car vous ne savez pas combien de temps les données sérialisées vont durer.

Voici un exemple d'utilisation.

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

REMARQUE : pour Java 7 et les versions antérieures, vous pouvez voir le réponse ici

Autres conseils

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

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

Merci pour vos réponses rapides et efficaces. Je renoncerai immédiatement à des votes pour remercier votre aide. J'ai codé la meilleure solution à mon avis en fonction 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();
}

Remarque : je n'ai pas envisagé d'utiliser JSON car son efficacité est moindre.

Remarque: je tiendrai compte de votre conseil de ne pas stocker un objet sérialisé sous forme de chaînes dans la base de données, mais plutôt d'octet [].

XStream fournit un utilitaire simple pour la sérialisation / désérialisation vers / depuis XML, et il est très rapide. Stocker des CLOBs XML plutôt que des BLOBs binaires sera moins fragile, pour ne pas dire plus lisible.

Pourquoi ne pas conserver l'objet en tant que blob

Si vous stockez un objet sous forme de données binaires dans la base de données, vous devez utiliser un type de données BLOB . La base de données est capable de la stocker plus efficacement et vous n'avez pas à vous soucier des encodages, etc. JDBC fournit des méthodes pour créer et récupérer des blobs en termes de flux. Si vous le pouvez, utilisez Java 6. Il a été possible d’ajouter à l’API JDBC des outils qui facilitent grandement la gestion des blobs.

Si vous devez absolument stocker les données sous forme de chaîne, je vous recommanderais XStream pour XML. stockage (beaucoup plus facile que XMLEncoder ), mais d’autres représentations d’objet 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.

Approche Java8, conversion de Object from / to String, inspirée de la réponse de OscarRyz . Pour le codage / codage, java.util.Base64 est requis et utilisé.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
import java.util.Optional;

interface ObjectHelper {

  static Optional<String> convertToString(final Serializable object) {
    try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos)) {
      oos.writeObject(object);
      return Optional.of(Base64.getEncoder().encodeToString(baos.toByteArray()));
    } catch (final IOException e) {
      e.printStackTrace();
      return Optional.empty();
    }
  }

  static <T extends Serializable> Optional<T> convertFrom(final String objectAsString) {
    final byte[] data = Base64.getDecoder().decode(objectAsString);
    try (final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
      return Optional.of((T) ois.readObject());
    } catch (final IOException | ClassNotFoundException e) {
      e.printStackTrace();
      return Optional.empty();
    }
  }
}

Le flux sérialisé est juste une séquence d'octets (octets). La question est donc de savoir comment convertir une séquence d'octets en chaîne, et inversement. De plus, il doit utiliser un ensemble limité de codes de caractères s'il doit être stocké dans une base de données.

La solution évidente au problème consiste à modifier le champ en LOB binaire. Si vous souhaitez vous en tenir à un caractère générique LOB, vous devez alors coder selon un schéma tel que base64, hex ou uu.

Vous pouvez utiliser les classes de construction sun.misc.Base64Decoder et sun.misc.Base64Encoder pour convertir les données binaires de la sérialisation en chaîne. Vous n’avez pas besoin de classes supplémentaires car elles sont intégrées.

Jetez un coup d'œil à la classe java.sql.PreparedStatement, plus précisément à la fonction

http://java.sun.com/javase/6/docs/api/java/sql/PreparedStatement.html#setBinaryStream (int,% 20java.io.InputStream)

Examinez ensuite la classe java.sql.ResultSet, plus précisément la fonction

.

http: // java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#getBinaryStream(int)

N'oubliez pas que si vous sérialisez un objet dans une base de données et que vous modifiez ensuite l'objet dans votre code dans une nouvelle version, le processus de désérialisation peut facilement échouer car la signature de votre objet a été modifiée. Une fois, j’ai commis cette erreur en enregistrant des préférences personnalisées sérialisées, puis en modifiant la définition des préférences. Tout à coup, je ne pouvais lire aucune des informations précédemment numérotées.

Il vaut peut-être mieux écrire dans un tableau des colonnes encombrantes par propriété, ainsi que composer et décomposer l’objet de cette manière, afin d’éviter ce problème avec les versions et la désérialisation des objets. Ou encore, écrivez les propriétés dans une table de hachage, comme un objet java.util.Properties, puis sérialisez l’objet properties qui est extrêmement peu susceptible de changer.

vous pouvez utiliser UUEncoding

Simple Solution, a travaillé pour moi

public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(obj);
    return out.toByteArray();
}

Utilisez un cadre O / R tel que hibernate

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top