157

次のコード スニペットに示すように、オブジェクトをファイルにシリアライズしてから、再度復元することができます。オブジェクトを文字列にシリアル化し、代わりにデータベースに保存したいと思います。誰でも私を助けることができますか?

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

13 に答える 13

281

セルジオ:

BLOBを使用する必要があります。JDBCではかなり簡単です。

投稿した2番目のコードの問題は、エンコーディングです。さらにバイトをエンコードして、いずれも失敗しないようにする必要があります。

それでも文字列に書き留めたい場合は、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以前の場合、元の回答はここに表示されます

于 2008-09-25T18:03:38.973 に答える
12

FileOutputStream の代わりに ByteArrayOutputStream にデータを書き込むのはどうですか?

それ以外の場合は、XMLEncoder を使用してオブジェクトをシリアル化し、XML を保持してから、XMLDecoder を介して逆シリアル化することができます。

于 2008-09-25T16:58:08.630 に答える
8

素早い返信ありがとうございます。あなたの助けに感謝するために、私はすぐにいくつかの票を放棄します. あなたの答えに基づいて、私の意見で最善の解決策をコーディングしました。

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[] を保存することについてのアドバイスを検討します。

于 2008-09-25T17:19:25.897 に答える
5

OscarRyz からの回答に触発された、オブジェクトを文字列との間で変換する Java8アプローチ。デコーディング/エンコーディングには、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;

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();
    }
  }
}
于 2017-06-02T11:54:42.397 に答える
4

XStreamは、XMLとの間でシリアル化/逆シリアル化するためのシンプルなユーティリティを提供し、非常に高速です。バイナリBLOBではなくXMLCLOBを格納すると、読みやすくなることは言うまでもなく、脆弱性が低くなります。

于 2008-09-25T19:57:15.270 に答える
4

オブジェクトをブロブとして永続化するのはどうですか

于 2008-09-25T17:01:01.807 に答える
3

オブジェクトをバイナリ データとしてデータベースに格納する場合は、BLOBデータ型を使用する必要があります。データベースはそれをより効率的に保存することができ、エンコーディングなどについて心配する必要はありません。JDBC は、ストリームに関して BLOB を作成および取得するためのメソッドを提供します。可能であれば Java 6 を使用してください。これにより、JDBC API にいくつかの追加が行われ、ブロブの処理が非常に簡単になりました。

データを文字列として保存する必要がある場合は、 XML ベースのストレージにXStreamをお勧めします (より簡単ですXMLEncoder) が、代わりのオブジェクト表現 (JSON など) も同様に役立つ場合があります。アプローチは、実際にこの方法でオブジェクトを保存する必要がある理由によって異なります。

于 2008-09-25T17:04:24.967 に答える
2

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)

オブジェクトをデータベースにシリアル化してから、コード内のオブジェクトを新しいバージョンで変更すると、オブジェクトの署名が変更されるため、逆シリアル化プロセスが簡単に失敗する可能性があることに注意してください。私はかつて、シリアル化されたカスタム設定を保存してから、設定定義を変更して、この間違いを犯しました。突然、以前に連載された情報が読めなくなりました。

オブジェクトのバージョンとデシリアライゼーションでこの問題を回避するには、代わりに、テーブルにプロパティ列ごとに不格好に記述し、この方法でオブジェクトを構成および分解する方がよい場合があります。または、プロパティを java.util.Properties オブジェクトなどの何らかのハッシュマップに書き込み、変更される可能性が非常に低いプロパティ オブジェクトをシリアル化します。

于 2008-09-25T18:18:07.237 に答える
1

シリアル化されたストリームは、一連のバイト (オクテット) です。したがって、問題は、一連のバイトを文字列に変換し、元に戻す方法です。さらに、データベースに格納する場合は、限られた文字コードのセットを使用する必要があります。

この問題の明白な解決策は、フィールドをバイナリ LOB に変更することです。文字の LOB を使用したい場合は、base64、hex、uu などのスキームでエンコードする必要があります。

于 2008-09-25T17:05:11.610 に答える
1

クラス sun.misc.Base64Decoder および sun.misc.Base64Encoder のビルドを使用して、シリアル化のバイナリ データを文字列に変換できます。組み込みなので、追加のクラスは必要ありません。

于 2008-09-25T18:38:18.577 に答える
0

UUEncoding を使用できます

于 2008-09-25T17:03:06.670 に答える