it-swarm.com.de

Wie wird ein Objekt in eine Zeichenfolge serialisiert?

Ich kann ein Objekt in eine Datei serialisieren und dann wieder herstellen, wie im nächsten Codeausschnitt dargestellt. Ich möchte das Objekt in einen String serialisieren und stattdessen in einer Datenbank speichern. Kann mir jemand helfen?

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();
137
Sergio del Amo

Sergio:

Sie sollten BLOB verwenden. Mit JDBC ist das recht einfach. 

Das Problem mit dem zweiten Code, den Sie gepostet haben, ist die Kodierung. Sie sollten die Bytes zusätzlich codieren, um sicherzustellen, dass keines von ihnen fehlschlägt.

Wenn Sie es dennoch in einen String schreiben möchten, können Sie die Bytes mit Java.util.Base64 kodieren. 

Sie sollten jedoch CLOB als Datentyp verwenden, da Sie nicht wissen, wie lange die serialisierten Daten sein werden.

Hier ist ein Beispiel, wie man es benutzt.

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;
    }
}

Ausgabe: 

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: für Java 7 und frühere Versionen können Sie die ursprüngliche antwort hier sehen

255
OscarRyz

Wie wäre es, die Daten in einen ByteArrayOutputStream anstatt in einen FileOutputStream zu schreiben?

Andernfalls können Sie das Objekt mit XMLEncoder serialisieren, das XML beibehalten und anschließend über XMLDecoder deserialisieren.

11

Danke für die tollen und schnellen Antworten. Ich werde einige Stimmen sofort aufgeben, um Ihre Hilfe anzuerkennen. Ich habe die beste Lösung meiner Meinung nach aufgrund Ihrer Antworten codiert. 

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

Hinweis Ich habe JSON nicht in Betracht gezogen, weil es weniger effizient ist.

Hinweis: Ich werde Ihren Rat befolgt, serialisierte Objekte nicht als Zeichenfolgen in der Datenbank zu speichern, sondern Byte []. 

7
Sergio del Amo

Wie wäre es, das Objekt als blob zu behalten? /

4
Kristian

XStream bietet ein einfaches Dienstprogramm für das Serialisieren/Deserialisieren von/nach XML, und es ist very quick. Das Speichern von XML-CLOBs anstelle von binären BLOBS wird weniger anfällig sein, geschweige denn lesbarer.

4
skaffman

Wenn Sie ein Objekt als binäre Daten in der Datenbank speichern, sollten Sie unbedingt einen BLOB-Datentyp verwenden. Die Datenbank kann sie effizienter speichern und Sie müssen sich keine Sorgen um Kodierungen oder ähnliches machen. JDBC bietet Methoden zum Erstellen und Abrufen von Blobs in Bezug auf Streams. Verwenden Sie Java 6, wenn Sie können, es hat einige Änderungen an der JDBC-API vorgenommen, die den Umgang mit Blobs erheblich erleichtern.

Wenn Sie die Daten unbedingt als String speichern müssen, würde ich XStream für XML-basierten Speicher empfehlen (viel einfacher als XMLEncoder), aber alternative Objektdarstellungen können genauso nützlich sein (z. B. JSON). Ihr Ansatz hängt davon ab, warum Sie das Objekt auf diese Weise tatsächlich speichern müssen.

3
Daniel Spiewak

Java8-Ansatz, der Object von/nach String konvertiert, angelehnt an die Antwort von OscarRyz Für De/Encoding ist Java.util.Base64 erforderlich und wird verwendet.

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();
    }
  }
}
2
Markus Schulte

Schauen Sie sich die Java.sql.PreparedStatement-Klasse an, insbesondere die Funktion

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

Dann werfen Sie einen Blick auf die Java.sql.ResultSet-Klasse, insbesondere die Funktion

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

Wenn Sie ein Objekt in eine Datenbank serialisieren und dann das Objekt in Ihrem Code in einer neuen Version ändern, kann der Deserialisierungsprozess leicht fehlschlagen, da sich die Signatur des Objekts geändert hat. Ich habe diesen Fehler einmal gemacht, indem ich eine benutzerdefinierte Voreinstellung serialisiert und dann die Voreinstellungsdefinition geändert habe. Plötzlich konnte ich keine der zuvor serialisierten Informationen lesen.

Möglicherweise sollten Sie nicht einfach clunky per Eigenschaftsspalten in eine Tabelle schreiben und das Objekt auf diese Weise erstellen und zerlegen, um dieses Problem bei Objektversionen und Deserialisierung zu vermeiden. Oder Sie schreiben die Eigenschaften in eine Hashmap irgendeiner Art, beispielsweise in ein Java.util.Properties-Objekt, und serialisieren dann das Eigenschaftenobjekt, dessen Änderung höchst unwahrscheinlich ist.

1
Josh

Der serialisierte Stream ist nur eine Folge von Bytes (Oktetts). Die Frage ist also, wie man eine Folge von Bytes in einen String und wieder zurück konvertiert. Außerdem muss ein begrenzter Satz von Zeichencodes verwendet werden, wenn er in einer Datenbank gespeichert werden soll.

Die offensichtliche Lösung des Problems besteht darin, das Feld in ein binäres LOB zu ändern. Wenn Sie bei einem Characer-LOB bleiben möchten, müssen Sie ein Schema wie base64, hex oder uu verwenden.

Sie können die Build-Klassen Sun.misc.Base64Decoder und Sun.misc.Base64Encoder verwenden, um die Binärdaten der Serialisierung in einen String zu konvertieren. Sie brauchen keine zusätzlichen Klassen, weil sie eingebaut sind.

1
Saboteur

sie können UUEncoding verwenden

0
CiNN

Einfache Lösung, arbeitete für mich

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