如何将对象序列化为字符串

我能够将一个对象序列化到一个文件中,然后再次恢复它,如下面的代码片段所示。我希望将对象序列化为一个字符串并存储到数据库中。有人能帮我吗?

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();
256545 次浏览

将数据写入 ByteArrayOutputStream 而不是 FileOutputStream 如何?

否则,您可以使用 XMLEncoder 序列化对象,持久化 XML,然后通过 XMLDecder 反序列化。

将对象持久化为 一团如何

可以使用 UUEncoding

如果将对象作为二进制数据存储在数据库中,那么实际上应该使用 BLOB数据类型。数据库能够更有效地存储它,而且您不必担心编码之类的问题。JDBC 提供了根据流创建和检索 blobs 的方法。如果可以的话使用 Java6,它对 JDBC API 做了一些补充,使得处理 blobs 变得更加容易。

如果您确实需要将数据存储为 String,我建议将 XStream用于基于 XML 的存储(比 XMLEncoder容易得多) ,但是替代对象表示也可能同样有用(例如 JSON)。您的方法取决于为什么实际上需要以这种方式存储对象。

序列化的流只是一个字节序列(八进制)。所以问题是如何将字节序列转换为 String,然后再转换回来。此外,如果要存储在数据库中,它需要使用一组有限的字符代码。

这个问题的显而易见的解决方案是将字段更改为二进制 LOB。如果希望使用字符 LOB,那么需要在一些方案中进行编码,如 base64、十六进制或 uu。

谢谢你的快速回复。为了感谢你们的帮助,我会立即放弃一些选票。根据你的回答,我想出了最好的解决方案。

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,因为它的效率较低。

注意: 我将考虑您的建议,即不要将序列化对象作为字符串存储在数据库中,而应将其作为 byte []存储。

塞吉奥:

你应该使用 一团。它对于 JDBC 来说非常简单。

您发布的第二个代码的问题是编码。您还应该对字节进行编码,以确保它们都不会失败。

如果仍然希望将其写入字符串,可以使用 Java.util Base64对字节进行编码。

但是您仍然应该使用 CLOB 作为数据类型,因为您不知道序列化的数据需要多长时间。

下面是如何使用它的一个示例。

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和更早版本,您可以在这里看到原始的 < a href = “ https://stackoverflow. com/Amendment/134918/9”> 答案

看一下 java.sql.PreparedStatement 类,特别是函数

Http://java.sun.com/javase/6/docs/api/java/sql/preparedstatement.html#setbinarystream (int,% 20java.io. inputStream)

然后查看 java.sql.ResultSet 类,特别是函数

Http://java.sun.com/javase/6/docs/api/java/sql/resultset.html#getbinarystream(int)

请记住,如果将对象序列化到数据库中,然后在新版本中更改代码中的对象,则反序列化过程很容易失败,因为对象的签名发生了更改。我曾经犯过这样的错误: 存储序列化的自定义 Preferences,然后更改 Preferences 定义。突然之间,我无法阅读任何以前连载的信息。

为了避免对象版本和反序列化的问题,您最好在表中为每个属性列编写笨拙的代码,并以这种方式组合和分解对象。或者将属性写入某种类型的散列表,比如 java.util。属性对象,然后序列化属性对象,这是极不可能改变的。

您可以在 sun.misc 类中使用构建。Base64解码器和 sun.misc。Base64Encoder 将序列化的二进制数据转换为字符串。您不需要额外的类,因为它是内建的。

XStream 提供了一个简单的实用程序,用于从 XML 序列化/反序列化,而且它是快速的 非常。存储 XMLCLOB 而不是二进制 BLOBS 将不那么脆弱,更不用说更具可读性。

Java8方法,将 Object 从/转换为 String,灵感来自 奥斯卡・瑞兹的答案。

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;


final class ObjectHelper {


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

简单解决方案,对我有效

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

目前最明显的方法是将对象保存为 JSON。

  1. JSON 是可读的
  2. 与 XML 相比,JSON 更易于阅读和使用。
  3. 许多允许直接存储 JSON 的非 SQL 数据库。
  4. 您的客户端已经使用 JSON 与服务器进行通信(如果没有,那么这很可能是一个错误)

使用 葛森的示例。

Gson gson = new Gson();
Person[] persons = getArrayOfPersons();
String json = gson.toJson(persons);
System.out.println(json);
//output: [{"name":"Tom","age":11},{"name":"Jack","age":12}]
Person[] personsFromJson = gson.fromJson(json, Person[].class);
//...
class Person {
public String name;
public int age;
}

Gson 允许直接转换 List 我更喜欢先把列表转换成数组。