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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/134492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:41:58  来源:igfitidea点击:

How to serialize an object into a string

javaserialization

提问by Sergio del Amo

I am able to serialize an object into a file and then restore it again as is shown in the next code snippet. I would like to serialize the object into a string and store into a database instead. Can anyone help me?

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

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

采纳答案by OscarRyz

Sergio:

塞尔吉奥:

You should use BLOB. It is pretty straighforward with JDBC.

你应该使用BLOB。使用 JDBC 非常简单。

The problem with the second code you posted is the encoding. You should additionally encode the bytes to make sure none of them fails.

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

If you still want to write it down into a String you can encode the bytes using java.util.Base64.

如果你仍然想把它写成一个字符串,你可以使用java.util.Base64对字节进行编码。

Still you should use CLOB as data type because you don't know how long the serialized data is going to be.

您仍然应该使用 CLOB 作为数据类型,因为您不知道序列化数据的长度。

Here is a sample of how to use it.

这是如何使用它的示例。

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

Output:

输出:

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: for Java 7 and earlier you can see the original answer here

注意:对于 Java 7 及更早版本,您可以在此处查看原始答案

回答by Outlaw Programmer

How about writing the data to a ByteArrayOutputStream instead of a FileOutputStream?

将数据写入 ByteArrayOutputStream 而不是 FileOutputStream 怎么样?

Otherwise, you could serialize the object using XMLEncoder, persist the XML, then deserialize via XMLDecoder.

否则,您可以使用 XMLEncoder 序列化对象,保留 XML,然后通过 XMLDecoder 反序列化。

回答by Kristian

Use a O/R framework such as hibernate

使用 O/R 框架,例如hibernate

回答by Kristian

How about persisting the object as a blob

如何将对象持久化为blob

回答by CiNN

you can use UUEncoding

你可以使用 UUEEncoding

回答by Daniel Spiewak

If you're storing an object as binary data in the database, then you really should use a BLOBdatatype. The database is able to store it more efficiently, and you don't have to worry about encodings and the like. JDBC provides methods for creating and retrieving blobs in terms of streams. Use Java 6 if you can, it made some additions to the JDBC API that make dealing with blobs a whole lot easier.

如果您将对象作为二进制数据存储在数据库中,那么您确实应该使用BLOB数据类型。数据库能够更有效地存储它,您不必担心编码等。JDBC 提供了根据流创建和检索 blob 的方法。如果可以,请使用 Java 6,它对 JDBC API 进行了一些补充,使处理 blob 变得更加容易。

If you absolutely need to store the data as a String, I would recommend XStreamfor XML-based storage (much easier than XMLEncoder), but alternative object representations might be just as useful (e.g. JSON). Your approach depends on why you actually need to store the object in this way.

如果您绝对需要将数据存储为字符串,我会推荐XStream用于基于 XML 的存储(比 容易得多XMLEncoder),但替代对象表示可能同样有用(例如 JSON)。您的方法取决于您实际需要以这种方式存储对象的原因。

回答by Tom Hawtin - tackline

The serialised stream is just a sequence of bytes (octets). So the question is how to convert a sequence of bytes to a String, and back again. Further it needs to use a limited set of character codes if it is going to be stored in a database.

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

The obvious solution to the problem is to change the field to a binary LOB. If you want to stick with a characer LOB, then you'll need to encode in some scheme such as base64, hex or uu.

该问题的明显解决方案是将字段更改为二进制 LOB。如果您想坚持使用字符 LOB,那么您需要以某种方案进行编码,例如 base64、hex 或 uu。

回答by Sergio del Amo

Thanks for great and quick replies. I will gives some up votes inmediately to acknowledge your help. I have coded the best solution in my opinion based on your answers.

感谢您的快速回复。我会立即放弃一些选票以感谢您的帮助。我已经根据您的回答编写了我认为的最佳解决方案。

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

Notei did not considered using JSON because is less efficient.

请注意,我没有考虑使用 JSON,因为效率较低。

Note:I will considered your advice about not storing serialized object as strings in the database but byte[] instead.

注意:我会考虑您关于不在数据库中将序列化对象存储为字符串而是 byte[] 的建议。

回答by Josh

Take a look at the java.sql.PreparedStatement class, specifically the function

看看java.sql.PreparedStatement类,具体的函数

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

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

Then take a look at the java.sql.ResultSet class, specifically the function

再看看java.sql.ResultSet类,具体是函数

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

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

Keep in mind that if you are serializing an object into a database, and then you change the object in your code in a new version, the deserialization process can easily fail because your object's signature changed. I once made this mistake with storing a custom Preferences serialized and then making a change to the Preferences definition. Suddenly I couldn't read any of the previously serialized information.

请记住,如果您将对象序列化到数据库中,然后在新版本中更改代码中的对象,则反序列化过程很容易失败,因为对象的签名已更改。我曾经在存储序列化的自定义首选项然后更改首选项定义时犯了这个错误。突然间,我无法阅读任何先前序列化的信息。

You might be better off writing clunky per property columns in a table and composing and decomposing the object in this manner instead, to avoid this issue with object versions and deserialization. Or writing the properties into a hashmap of some sort, like a java.util.Properties object, and then serializing the properties object which is extremely unlikely to change.

您最好在表中编写笨重的每个属性列,然后以这种方式组合和分解对象,以避免对象版本和反序列化出现此问题。或者将属性写入某种类型的哈希映射,例如 java.util.Properties 对象,然后序列化极不可能更改的属性对象。

回答by Josh

You can use the build in classes sun.misc.Base64Decoder and sun.misc.Base64Encoder to convert the binary data of the serialize to a string. You das not need additional classes because it are build in.

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