如何序列化一个对象到一个string
我能够序列化一个对象到一个文件,然后再次恢复它,如下面的代码片段所示。 我想序列化成一个string的对象,而不是存储到数据库中。 任何人都可以帮我吗?
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();
塞尔吉奥:
你应该使用BLOB 。 JDBC非常直接。
您发布的第二个代码的问题是编码。 你应该额外编码字节,以确保他们没有失败。
如果你仍然想把它写入string中,你可以使用java.util.Base64来编码字节。
仍然应该使用CLOB作为数据types,因为您不知道序列化的数据将要多长时间。
这里是一个如何使用它的例子。
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; } }
输出:
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
注意 :对于Java 7和更早版本,您可以在这里看到原始的答案
如何将数据写入ByteArrayOutputStream而不是FileOutputStream?
否则,您可以使用XMLEncoder序列化对象,保留XML,然后通过XMLDecoder反序列化。
感谢您的回复。 我会立即提供一些赞成票来表示你的帮助。 根据你的回答,我已经根据我的观点编写了最好的解决scheme。
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(); }
注意我没有考虑使用JSON,因为效率较低。
注意:我会考虑你的build议,不要将序列化的对象作为string存储在数据库中,而是使用byte []来代替。
如何坚持对象作为一个blob
XStream为XML序列化/反序列化提供了一个简单的实用程序,而且非常快速。 存储XML CLOB而不是二进制BLOBS将不那么脆弱,更不用说更多的可读性。
如果要将对象作为二进制数据存储在数据库中,则应该使用BLOB
数据types。 数据库能够更高效地存储数据,而且不必担心编码等问题。 JDBC提供了根据stream创build和检索blob的方法。 如果可以的话,使用Java 6,它增加了一些JDBC API,使处理blob变得更容易。
如果您绝对需要将数据存储为string,那么我会推荐基于XML的存储的XStream (比XMLEncoder
更容易),但是替代对象表示可能同样有用(例如JSON)。 你的方法取决于你为什么需要以这种方式存储对象。
序列化的stream只是一个字节序列(八位字节)。 所以问题是如何将一个字节序列转换为一个string,然后再回来。 此外,如果将要存储在数据库中,则需要使用有限的一组字符代码。
问题的明显解决scheme是将该字段更改为二进制LOB。 如果你想坚持一个字符的LOB,那么你需要编码在一些计划,如base64,hex或uu。
您可以使用sun.misc.Base64Decoder和sun.misc.Base64Encoder类中的构build将serialize的二进制数据转换为string。 你不需要额外的类,因为它是内置的。
看看java.sql.PreparedStatement类,特别是函数
然后看看java.sql.ResultSet类,特别是函数
http://java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#getBinaryStream(int);
请记住,如果您将对象序列化到数据库中,然后在新版本中更改代码中的对象,则反序列化过程可能会因为对象的签名更改而很容易失败。 我曾经犯了这个错误,存储一个自定义首选项序列化,然后改变首选项定义。 突然间,我无法读取任何以前的序列化信息。
你可能会更好的写一个表格中的每个属性列的笨拙,并以这种方式组合和分解对象,以避免与对象版本和反序列化的这个问题。 或者将属性写入某种类的散列映射(如java.util.Properties对象),然后序列化非常不可能改变的属性对象。
你可以使用UUEncoding
Java8方法,将Object从/转换为String,由OscarRyz的答案启发。 对于de / /编码, java.util.Base64是必需和使用的。
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(); } } }
简单的解决scheme,为我工作
public static byte[] serialize(Object obj) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(out); os.writeObject(obj); return out.toByteArray(); }
使用诸如hibernate的O / R框架