我能够将一个对象序列化为一个文件然后再次恢复它,如下一个代码片段所示。我想将对象序列化为字符串并存储到数据库中。任何人都可以帮助我吗?
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();
答案 0 :(得分:257)
塞吉奥:
您应该使用BLOB。使用JDBC非常简单。
您发布的第二个代码的问题是编码。您还应该对字节进行编码,以确保它们都不会失败。
如果您仍想将其写入String,则可以使用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及更早版本,您可以看到原始的answer here
答案 1 :(得分:11)
如何将数据写入ByteArrayOutputStream而不是FileOutputStream?
否则,您可以使用XMLEncoder序列化对象,保留XML,然后通过XMLDecoder反序列化。
答案 2 :(得分:7)
感谢您的快速回复。我会立即给予一些投票,以表示你的帮助。我根据你的答案在我看来编写了最好的解决方案。
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 []存储。
答案 3 :(得分:4)
如何将对象保存为blob
答案 4 :(得分:4)
XStream提供了一个简单的实用程序,用于对XML进行序列化/反序列化,并且非常快速。存储XML CLOB而不是二进制BLOBS将不那么脆弱,更不用说更具可读性了。
答案 5 :(得分:3)
如果您将对象作为二进制数据存储在数据库中,那么您真的应该使用BLOB
数据类型。数据库能够更有效地存储它,您不必担心编码等。 JDBC提供了根据流创建和检索blob的方法。如果可以的话,使用Java 6,它对JDBC API进行了一些补充,使得处理blob变得更加容易。
如果您绝对需要将数据存储为字符串,我建议XStream用于基于XML的存储(比XMLEncoder
容易得多),但替代对象表示可能同样有用(例如JSON)。您的方法取决于您实际需要以这种方式存储对象的原因。
答案 6 :(得分:2)
Java8方法,将Object从/转换为String,灵感来自OscarRyz的答案。对于解/编码,需要使用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();
}
}
}
答案 7 :(得分:1)
序列化流只是一个字节序列(八位字节)。所以问题是如何将字节序列转换为String,然后再返回。此外,如果要将其存储在数据库中,则需要使用一组有限的字符代码。
该问题的明显解决方案是将字段更改为二进制LOB。如果你想坚持使用characer LOB,那么你需要在某些方案中进行编码,例如base64,hex或uu。
答案 8 :(得分:1)
查看java.sql.PreparedStatement类,特别是函数
然后看一下java.sql.ResultSet类,特别是函数
http://java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#getBinaryStream(int)
请记住,如果要将对象序列化到数据库中,然后在新版本中更改代码中的对象,则反序列化过程很容易失败,因为对象的签名已更改。我曾经犯过这样的错误,即存储自定义的序列化首选项,然后更改首选项定义。突然间,我无法读取任何先前序列化的信息。
最好不要在表中编写每个属性列的clunky,而是以这种方式组合和分解对象,以避免对象版本和反序列化的这个问题。或者将属性写入某种类型的hashmap,如java.util.Properties对象,然后序列化极不可能更改的属性对象。
答案 9 :(得分:1)
您可以使用sun.misc.Base64Decoder和sun.misc.Base64Encoder类中的内置版本将序列化的二进制数据转换为字符串。你不需要额外的类,因为它是内置的。
答案 10 :(得分:0)
您可以使用UUEncoding
答案 11 :(得分:0)
简单的解决方案,为我工作
// Add to admin_menu function
$page = add_submenu_page( 'edit.php?post_type=theme', __('Theme Page Options'), __('Theme Menu Options'), 'edit_themes', 'theme_options', theme_options);
function theme_options() {
// Render our theme options page here ...
}
答案 12 :(得分:0)
当今最明显的方法是将对象保存到JSON。
使用Gson的示例。
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。例子很容易 谷歌搜索。我更喜欢先将列表转换为数组。
答案 13 :(得分:-2)
使用O / R框架,例如hibernate