किसी स्ट्रिंग में किसी ऑब्जेक्ट को क्रमबद्ध कैसे करें


150

मैं किसी फ़ाइल में किसी ऑब्जेक्ट को क्रमबद्ध करने में सक्षम हूं और फिर इसे फिर से पुनर्स्थापित कर सकता हूं जैसा कि अगले कोड स्निपेट में दिखाया गया है। मैं एक स्ट्रिंग में ऑब्जेक्ट को क्रमबद्ध करना और इसके बजाय डेटाबेस में स्टोर करना चाहूंगा। क्या कोई मेरी मदद कर सकता है?

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

जवाबों:


270

सर्जियो:

आपको 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

नोट : जावा 7 के लिए और पहले आप यहां मूल उत्तर देख सकते हैं


+1 यदि आपको वास्तव में स्ट्रिंग्स की आवश्यकता है, तो बेस 64 + क्लोब जाने का रास्ता है।
जॉन गार्डनर

6
+1, छोटा सुधार। इंटरफ़ेस का उपयोग करने के लिए बेहतर है प्लेन ऑब्जेक्ट के बजाय
सीरियल स्ट्रेसिंग

4
यदि हम स्ट्रिंग के बजाय ऑब्जेक्ट को बाइट सरणी के रूप में संग्रहीत करने का प्रयास करते हैं, तो हम BASE64 का उपयोग किए बिना नमूना प्राप्त कर सकते हैं।
सुदार

2
इसमें घातक दोष यह है कि वर्ग की परिभाषाएँ समय के साथ बदलती रहती हैं - यदि ऐसा परिवर्तन होता है तो आप निराशा में असमर्थ होंगे! वसीयत जोड़ने serialVersionUIDसे SomeClassनए क्षेत्रों को जोड़ा जा रहा है, लेकिन यदि फ़ील्ड निकाल दी जाती हैं तो आपको खराब कर दिया जाएगा। यह पढ़ने योग्य है कि जोशुआ बलोच ने इस पर प्रभावी जावा में क्या कहा है - books.google.co.uk/…
निक होल

1
जावा 8 के बाद से अब java.util.Base64 है। आपको अपना उत्तर अपडेट करना चाहिए: Base64.getEncoder (); encodeToString (baos.toByteArray ()); Base64.getDecoder () डिकोड (रों)।
drUniversalis

12

कैसे एक FileOutputStream के बजाय एक ByteArrayOutputStream डेटा लिखने के बारे में?

अन्यथा, आप xmlncoder का उपयोग करके ऑब्जेक्ट को क्रमबद्ध कर सकते हैं, XML को जारी रख सकते हैं, फिर XMLDecoder के माध्यम से deserialize कर सकते हैं।


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 का उपयोग करने पर विचार नहीं किया क्योंकि कम कुशल है।

नोट: मैं डेटाबेस में तार के रूप में क्रमबद्ध ऑब्जेक्ट को संग्रहीत न करने के बारे में आपकी सलाह पर विचार करूंगा लेकिन इसके बजाय बाइट []।


3
"ByteArrayOutputStream.toString प्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग का उपयोग करके धर्मान्तरित करता है । क्या आप सुनिश्चित हैं कि आप चाहते हैं? विशेष रूप से एक मनमाने ढंग से बाइट सरणी के रूप में मान्य UTF8 नहीं है। आगे, डेटाबेस इसे mangle करने जा रहा है।"
टॉम हॉल्टिन - 17

आपको टॉम
हॉकिन

अनुक्रमित वस्तुओं के दीर्घकालिक भंडारण का उल्लेख नहीं करना एक महान विचार नहीं है और इसकी सिफारिश नहीं की गई है
स्टीव जी

"नोट मैंने JSON का उपयोग करने पर विचार नहीं किया क्योंकि कम कुशल है।" दक्षता के लिए Google के प्रोटोकॉल बफ़र्स का उपयोग कैसे करें? इसके अलावा, स्टीव जी का विचार एकदम सही है। एक DB में क्रमबद्ध डेटा को स्टोर करने का एक तरीका अभी तक जावा के अलावा अन्य भाषाओं के लिए उपलब्ध है, प्रोटोकॉल बफ़र्स है।
अंजनब

5

Java8 दृष्टिकोण, स्ट्रिंग के लिए / से परिवर्तित वस्तु, से जवाब से प्रेरित OscarRyz । De- / एन्कोडिंग के लिए, 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();
    }
  }
}

यह क्लास के बजाय एक इंटरफ़ेस क्यों है?
simonalexander2005

@ simonalexander2005 सार्थक नोट, मैं अब यहाँ एक इंटरफ़ेस का उपयोग नहीं करेगा। मैंने इसे बदल दिया।
मार्कस शुल्टे

4

एक्सस्ट्रीम एक्सएमएल से / के लिए सीरियलाइज़िंग / डिसेरिएलाइज़िंग के लिए एक सरल उपयोगिता प्रदान करता है, और यह बहुत जल्दी है। बाइनरी BLOBS के बजाय XML CLOB का भंडारण कम नाजुक होने वाला है, अधिक पठनीय का उल्लेख नहीं करने के लिए।



3

यदि आप डेटाबेस में बाइनरी डेटा के रूप में एक ऑब्जेक्ट स्टोर कर रहे हैं, तो आपको वास्तव में BLOBडेटाटाइप का उपयोग करना चाहिए । डेटाबेस इसे और अधिक कुशलता से संग्रहीत करने में सक्षम है, और आपको एन्कोडिंग और इस तरह की चिंता करने की आवश्यकता नहीं है। JDBC धाराओं के संदर्भ में बूँदें बनाने और पुनः प्राप्त करने के लिए तरीके प्रदान करता है। जावा 6 का उपयोग करें यदि आप कर सकते हैं, तो इसने जेडीबीसी एपीआई के लिए कुछ परिवर्धन किए हैं जो एक पूरे बहुत आसान के साथ काम कर रहे हैं।

यदि आपको डेटा को स्ट्रिंग के रूप में संग्रहीत करने की आवश्यकता है, तो मैं XML- आधारित भंडारण के लिए XStream की सलाह दूंगा (की तुलना में बहुत आसान XMLEncoder), लेकिन वैकल्पिक वस्तु प्रतिनिधित्व केवल उपयोगी हो सकता है (जैसे JSON)। आपका दृष्टिकोण इस बात पर निर्भर करता है कि आपको वास्तव में इस तरह से ऑब्जेक्ट को स्टोर करने की आवश्यकता क्यों है।


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 ऑब्जेक्ट, और फिर गुण ऑब्जेक्ट को क्रमबद्ध करना जो बदलने की संभावना नहीं है।


1

क्रमबद्ध धारा केवल बाइट्स (ओकटेट्स) का एक अनुक्रम है। तो सवाल यह है कि बाइट्स के अनुक्रम को स्ट्रिंग में कैसे परिवर्तित किया जाए, और फिर से वापस। इसके अलावा अगर इसे किसी डेटाबेस में संग्रहित किया जाना है तो इसे सीमित वर्ण कोड का उपयोग करना होगा।

समस्या का स्पष्ट समाधान क्षेत्र को एक बाइनरी एलओबी में बदलना है। यदि आप एक चरवाहा LOB के साथ रहना चाहते हैं, तो आपको कुछ योजनाओं जैसे कि बेस 64, हेक्स या यूयू में एनकोड करना होगा।


1

आप निर्माण का उपयोग वर्गों में कर सकते हैं sun.misc.Base64Decoder और sun.misc.Base64Encoder क्रमबद्ध के बाइनरी डेटा को एक स्ट्रिंग में बदलने के लिए। आपको अतिरिक्त कक्षाओं की आवश्यकता नहीं है क्योंकि इसमें निर्माण किया जाता है।



0

सरल समाधान, मेरे लिए काम किया

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.