Como serializar um object em uma string

Eu sou capaz de serializar um object em um arquivo e restaurá-lo novamente como é mostrado no próximo trecho de código. Eu gostaria de serializar o object em uma seqüência de caracteres e armazenar em um database em vez disso. Alguém pode me ajudar?

LinkedList 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 patches3 = (LinkedList) one; os.close(); 

Sergio:

Você deveria usar BLOB . É bem simples com o JDBC.

O problema com o segundo código que você postou é a codificação. Você também deve codificar os bytes para garantir que nenhum deles falhe.

Se você ainda quiser escrevê-lo em uma String, poderá codificar os bytes usando java.util.Base64 .

Ainda assim, você deve usar o CLOB como tipo de dados porque não sabe quanto tempo os dados serializados serão.

Aqui está uma amostra de como usá-lo.

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

Saída:

 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 

NOTA : para o Java 7 e versões anteriores, você pode ver a resposta original aqui

Que tal escrever os dados em um ByteArrayOutputStream em vez de um FileOutputStream?

Caso contrário, você poderia serializar o object usando XMLEncoder, persistir o XML e, em seguida, desserializar via XMLDecoder.

Obrigado por respostas excelentes e rápidas. Eu darei alguns votos imediatamente para agradecer sua ajuda. Eu codifiquei a melhor solução na minha opinião com base nas suas respostas.

 LinkedList 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 restored_patches1 = (LinkedList) oInputStream.readObject(); // patches1 equals restored_patches1 oInputStream.close(); } catch(Exception ex) { ex.printStackTrace(); } 

Note que não considerei usar JSON porque é menos eficiente.

Nota: Eu considerarei seu conselho sobre não armazenar objects serializados como strings no database, mas sim byte [].

O XStream fornece um utilitário simples para serializar / desserializar para / de XML, e é muito rápido. Armazenar XML CLOBs ao invés de BLOBS binários será menos frágil, para não mencionar mais legível.

Que tal persistir o object como um blob

Se você está armazenando um object como dados binários no database, você deve usar um tipo de dados BLOB . O database pode armazená-lo de maneira mais eficiente e você não precisa se preocupar com codificações e afins. O JDBC fornece methods para criar e recuperar blobs em termos de streams. Use o Java 6 se você puder, ele fez algumas adições à API do JDBC que facilitam muito o trabalho com blobs.

Se você realmente precisar armazenar os dados como uma String, eu recomendaria o XStream para armazenamento baseado em XML (muito mais fácil que o XMLEncoder ), mas as representações de objects alternativos podem ser tão úteis (por exemplo, JSON). Sua abordagem depende do motivo pelo qual você realmente precisa armazenar o object dessa maneira.

O stream serializado é apenas uma seqüência de bytes (octetos). Então a questão é como converter uma seqüência de bytes em uma String e vice-versa. Além disso, ele precisa usar um conjunto limitado de códigos de caracteres se for armazenado em um database.

A solução óbvia para o problema é alterar o campo para um LOB binário. Se você quiser ficar com um LOB characer, então você precisa codificar em algum esquema, como base64, hex ou uu.

Você pode usar a construção nas classs sun.misc.Base64Decoder e sun.misc.Base64Encoder para converter os dados binários da serialização em uma string. Você não precisa de classs adicionais porque elas são construídas.

Dê uma olhada na class java.sql.PreparedStatement, especificamente na function

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

Então dê uma olhada na class java.sql.ResultSet, especificamente na function

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

Tenha em mente que, se você estiver serializando um object em um database e, em seguida, alterar o object em seu código em uma nova versão, o processo de desserialização poderá falhar facilmente porque a assinatura do object foi alterada. Certa vez, cometi esse erro ao armazenar uma preferência personalizada serializada e, em seguida, fazer uma alteração na definição Preferências. De repente, não consegui ler nenhuma informação previamente serializada.

Talvez seja melhor escrever frases desajeitadas por propriedade em uma tabela e compor e decompor o object dessa maneira, para evitar esse problema com versões de object e desserialização. Ou gravar as propriedades em um hashmap de algum tipo, como um object java.util.Properties e, em seguida, serializar o object de propriedades que é extremamente improvável que seja alterado.

você pode usar UUEncoding

Abordagem Java8, convertendo Object de / para String, inspirado na resposta de OscarRyz . Para de- / codificação, java.util.Base64 é necessário e usado.

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

Solução Simples, funcionou para mim

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

Use uma estrutura de O / R, como hibernate