[java] 객체를 문자열로 직렬화하는 방법

객체를 파일로 직렬화 한 다음 다음 코드 스 니펫에 표시된 것처럼 다시 복원 할 수 있습니다. 객체를 문자열로 직렬화하고 대신 데이터베이스에 저장하고 싶습니다. 누구든지 나를 도울 수 있습니까?

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를 사용하면 매우 간단합니다.

게시 한 두 번째 코드의 문제점은 인코딩입니다. 실패하지 않도록 바이트를 추가로 인코딩해야합니다.

여전히 문자열에 쓰려면 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 및 이전 버전의 경우 원래 답변을 볼 수 있습니다.


답변

FileOutputStream 대신 ByteArrayOutputStream에 데이터를 쓰는 것은 어떻습니까?

그렇지 않으면 XMLEncoder를 사용하여 객체를 직렬화하고 XML을 유지 한 다음 XMLDecoder를 통해 역 직렬화 할 수 있습니다.


답변

훌륭하고 빠른 답변에 감사드립니다. 나는 당신의 도움을 인정하기 위해 즉시 투표를합니다. 귀하의 답변에 따라 내 의견으로는 최고의 솔루션을 코딩했습니다.

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 []에 대한 조언을 고려할 것입니다.


답변

에서 대답에서 영감을 Java8 방법, 문자열에 /에서 변환 개체 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;

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


답변

XStream은 XML과의 직렬화 / 직렬화를위한 간단한 유틸리티를 제공하며 매우 빠릅니다. 이진 BLOBS가 아닌 XML CLOB를 저장하면 더 쉽게 읽을 수있는 것은 말할 것도없고 덜 취약합니다.


답변

개체를 얼룩 으로 유지하는 방법


답변

데이터베이스에 객체를 이진 데이터로 저장하는 경우 실제로 BLOB데이터 유형을 사용해야합니다 . 데이터베이스는 데이터베이스를보다 효율적으로 저장할 수 있으므로 인코딩 등에 대해 걱정할 필요가 없습니다. JDBC는 스트림 측면에서 블롭을 작성하고 검색하는 메소드를 제공합니다. 가능하면 Java 6을 사용하면 JDBC API를 추가하여 얼룩을 훨씬 쉽게 처리 할 수 ​​있습니다.

데이터를 String으로 저장 해야하는 경우 XML 기반 스토리지 용 XStream 을 권장 XMLEncoder하지만 () 보다 대체 객체 표현이 유용 할 수 있습니다 (예 : JSON). 이 방법으로 실제로 객체를 저장해야하는 이유에 따라 접근 방식이 달라집니다.