2010-01-19 23 views
10

अब जब मैं किसी ऑब्जेक्ट को जोड़ने का प्रयास करता हूं तो मुझे java.io.StreamCorruptedException मिल जाएगा। मैंने इसे दूर करने के लिए इंटरनेट की खोज की है। अब तक जो जवाब मिला है वह यह नहीं किया जा सकता है। इस समस्या के आसपास एक तरीका वस्तुओं को एक सूची में लिखना है और फिर फ़ाइल को सूची लिखना है।मैं मौजूदा java.io.ObjectStream में कैसे जोड़ सकता हूं?

लेकिन मैं उस फ़ाइल को हर अधिलेखित करने के लिए जब मैं नई वस्तुओं को जोड़ने की है। ऐसा लगता है कि ओवरटाइम में इष्टतम समाधान नहीं है।

वहाँ किसी मौजूदा ऑब्जेक्ट धारा वस्तुओं संलग्न करने के लिए एक तरीका है?

+3

क्या आपके पास कोई प्रश्न है? – danben

+0

क्या आपके लिए दृढ़ता के लिए डेटाबेस का उपयोग करना संभव है? – Asaph

+0

@ डैनबेन: हाँ, सवाल यह है कि यदि वस्तुओं को किसी फ़ाइल में जोड़ा जा सकता है। @ एसाफ: मैं ऐसा कर सकता था, लेकिन मैं जानना चाहता हूं कि वस्तुओं के लिए परिशिष्ट नहीं है या नहीं। सूखी अगर मेरे प्रश्न ने इसे स्पष्ट नहीं किया। – starcorn

उत्तर

5

यह वास्तव में करना बहुत आसान है। जब आप किसी मौजूदा स्ट्रीम में जोड़ रहे हैं तो आपको ऑब्जेक्टऑटस्ट्रीम के उप-वर्ग का उपयोग करने की आवश्यकता है जो writeStreamHeader को ओवरराइड करता है ताकि फ़ाइल के मध्य में दूसरा हेडर लिखा न जाए। उदाहरण

लिए
class NoHeaderObjectOutputStream extends ObjectOutputStream { 
    public NoHeaderObjectOutputStream(OutputStream os) { 
    super(os); 
    } 
    protected void writeStreamHeader() {} 
} 

तो बस एक मानक ObjectInputStream का उपयोग पूरी फ़ाइल को पढ़ने के लिए।

+0

में पाया गया writeObject() विधि का उपयोग करना बहुत अच्छा, शून्य लिखना (बाइट [] बी, int off, int len, बूलियन प्रति) दुर्भाग्य से निजी विधि लिखने का उपयोग करता हैब्लॉकहेडर। – stacker

+0

अच्छा, यह काम करता है :) – starcorn

+0

+1 मैंने इसे प्रलेखन में पढ़ा लेकिन (जैसा कि यह अक्सर मुझे प्रलेखन के साथ होता है) अब तक मुझे काफी कुछ नहीं मिला। – OscarRyz

0

आप एक नया ObjectInputStream हर ObjectOutputStream मैच के लिए बनाने के लिए की आवश्यकता होगी। मुझे ObjectInputStream से ObjectOutputStream (पूरी तरह से पुन: कार्यान्वयन के बिना, जो कि शुद्ध जावा में थोड़ा मुश्किल है) से राज्य को स्थानांतरित करने का कोई तरीका नहीं है।

5

सबसे अच्छा लेख मैं इस विषय पर मिल गया है है: http://codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/

"समाधान" कि ओवरराइड करता है ObjectOutputStream बस गलत है। मैंने अभी एक बग की जांच पूरी कर ली है जो उसके कारण हुई थी (दो कीमती दिन बर्बाद कर रही थी)। इतना ही नहीं कि यह कभी-कभी धारावाहिक फ़ाइल को दूषित करता है लेकिन अंत में अपवाद फेंकने के बिना भी पढ़ा जाता है और अंत में कचरा डेटा (मिश्रण क्षेत्र) प्रदान करता है।

समाधान # 1::

import java.io.*; 
import java.util.HashMap; 
import java.util.Map; 

public class Main { 

    public static void main(String[] args) throws Exception { 

     File storageFile = new File("test"); 
     storageFile.delete(); 

     write(storageFile, getO1()); 
     write(storageFile, getO2()); 
     write(storageFile, getO2()); 

     ObjectInputStream ois = new ObjectInputStream(new FileInputStream(storageFile)); 
     read(ois, getO1()); 
     read(ois, getO2()); 
     read(ois, getO2()); 
    } 

    private static void write(File storageFile, Map<String, String> o) throws IOException { 
     ObjectOutputStream oos = getOOS(storageFile); 
     oos.writeObject(o); 
     oos.close(); 
    } 

    private static void read(ObjectInputStream ois, Map<String, String> expected) throws ClassNotFoundException, IOException { 
     Object actual = ois.readObject(); 
     assertEquals(expected, actual); 
    } 

    private static void assertEquals(Object o1, Object o2) { 
     if (!o1.equals(o2)) { 
      throw new AssertionError("\n expected: " + o1 + "\n actual: " + o2); 
     } 
    } 

    private static Map<String, String> getO1() { 
     Map<String, String> nvps = new HashMap<String, String>(); 
     nvps.put("timestamp", "1326382770000"); 
     nvps.put("length", "246"); 
     return nvps; 
    } 

    private static Map<String, String> getO2() { 
     Map<String, String> nvps = new HashMap<String, String>(); 
     nvps.put("timestamp", "0"); 
     nvps.put("length", "0"); 
     return nvps; 
    } 

    private static ObjectOutputStream getOOS(File storageFile) throws IOException { 
     if (storageFile.exists()) { 
      // this is a workaround so that we can append objects to an existing file 
      return new AppendableObjectOutputStream(new FileOutputStream(storageFile, true)); 
     } else { 
      return new ObjectOutputStream(new FileOutputStream(storageFile)); 
     } 
    } 

    private static class AppendableObjectOutputStream extends ObjectOutputStream { 

     public AppendableObjectOutputStream(OutputStream out) throws IOException { 
      super(out); 
     } 

     @Override 
     protected void writeStreamHeader() throws IOException { 
      // do not write a header 
     } 
    } 
} 

के रूप में है कि लेख में कहा गया है, तो आपको निम्न समाधानों में से एक का उपयोग कर सकते हैं: अविश्वास में उन लोगों के लिए, मैं कुछ कोड है कि समस्या को उजागर करता है संलग्न कर रहा हूँ नकली एक एकल स्ट्रीम

में एकाधिक फ़ाइल ...

एक ByteArrayOutputStream के लिए अपने "लेन-देन" लिखें, फिरबारे में डेटाऑटपुटस्ट्रीम के माध्यम से इस फ़ाइल द्वारा 10 लंबाई और सामग्री ByteArrayOutputStream।

समाधान # 2: फिर से खोलें और छोड़ें

एक अन्य समाधान का उपयोग कर फ़ाइल स्थिति बचत शामिल है:

long pos = fis.getChannel().position(); 

, फ़ाइल को बंद करने फ़ाइल को फिर से खोलने, और पढ़ने से पहले इस स्थिति को लंघन अगला लेनदेन

+0

यहां फ़ंक्शन की एक जोड़ी है (स्कैला में) जो समाधान # 1 लागू करती है –

2

समस्या को उजागर करने के लिए कोड जॉर्ज Hategan लिए बहुत धन्यवाद। मैंने थोड़ी देर के लिए भी इसकी जांच की। फिर, यह मुझे मारा।आप डेटा लिखने के लिए एक उप-वर्गीकृत ObjectOutputStreamwriteStreamHeader() है, जिसकी ओवरराइड साथ विधि का उपयोग कर रहे हैं, तो आप है, जिसकी ओवरराइड के साथ समानांतर उप वर्गीकृत ObjectInputStream का उपयोग करना चाहिए डेटा पढ़ने के लिए readStreamHeader() विधि। बेशक, हम लेखन और पढ़ने की वस्तुओं के विभिन्न कार्यान्वयन के बीच ज़िग-ज़ैग कर सकते हैं, लेकिन जब तक हम लिखने/पढ़ने की प्रक्रिया में उप-वर्गों के संबंधित जोड़े का उपयोग करते हैं - हम (उम्मीदपूर्वक) ठीक होंगे। टॉम।

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.OutputStream; 
import java.util.HashMap; 
import java.util.Map; 

public class SerializationDemo { 

    public static void main(String[] args) throws Exception { 
     File storageFile = new File("test.ser"); 
     storageFile.delete(); 
     write(storageFile, getO1()); 
     write(storageFile, getO2()); 
     write(storageFile, getO2()); 
     FileInputStream fis = new FileInputStream(storageFile); 
     read(fis, getO1()); 
     read(fis, getO2()); 
     read(fis, getO2()); 
     fis.close(); 
    } 

    private static void write(File storageFile, Map<String, String> o) 
        throws IOException { 
     ObjectOutputStream oos = getOOS(storageFile); 
     oos.writeObject(o); 
     oos.flush(); 
     oos.close(); 
    } 

    private static void read(FileInputStream fis, Map<String, String> expected) 
        throws ClassNotFoundException, IOException { 
     Object actual = getOIS(fis).readObject(); 
     assertEquals(expected, actual); 
     System.out.println("read serialized " + actual); 
    } 

    private static void assertEquals(Object o1, Object o2) { 
     if (!o1.equals(o2)) { 
      throw new AssertionError("\n expected: " + o1 + "\n actual: " + o2); 
     } 
    } 

    private static Map<String, String> getO1() { 
     Map<String, String> nvps = new HashMap<String, String>(); 
     nvps.put("timestamp", "1326382770000"); 
     nvps.put("length", "246"); 
     return nvps; 
    } 

    private static Map<String, String> getO2() { 
     Map<String, String> nvps = new HashMap<String, String>(); 
     nvps.put("timestamp", "0"); 
     nvps.put("length", "0"); 
     return nvps; 
    } 

    private static ObjectOutputStream getOOS(File storageFile) 
        throws IOException { 
     if (storageFile.exists()) { 
      // this is a workaround so that we can append objects to an existing file 
      return new AppendableObjectOutputStream(new FileOutputStream(storageFile, true)); 
     } else { 
      return new ObjectOutputStream(new FileOutputStream(storageFile)); 
     } 
    } 

    private static ObjectInputStream getOIS(FileInputStream fis) 
        throws IOException { 
     long pos = fis.getChannel().position(); 
     return pos == 0 ? new ObjectInputStream(fis) : 
      new AppendableObjectInputStream(fis); 
    } 

    private static class AppendableObjectOutputStream extends 
        ObjectOutputStream { 

     public AppendableObjectOutputStream(OutputStream out) 
         throws IOException { 
      super(out); 
     } 

     @Override 
     protected void writeStreamHeader() throws IOException { 
      // do not write a header 
     } 
    } 

    private static class AppendableObjectInputStream extends ObjectInputStream { 

     public AppendableObjectInputStream(InputStream in) throws IOException { 
      super(in); 
     } 

     @Override 
     protected void readStreamHeader() throws IOException { 
      // do not read a header 
     } 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे