2009-04-17 22 views
24

जावा में दो इनपुटस्ट्रीम होने के कारण, उन्हें मर्ज करने का कोई तरीका है ताकि आप एक इनपुटस्ट्रीम के साथ समाप्त हो जाएं जो आपको दोनों धाराओं का आउटपुट देता है? कैसे?आप जावा में दो इनपुट स्ट्रीम कैसे मर्ज करते हैं?

+3

वास्तव में किस तरह से विलय? पहली बार पढ़ने के बाद एक दूसरी धारा से पढ़ना जारी रखें? मैं जावा से बहुत परिचित नहीं हूं, लेकिन सी # में आप धाराओं से उत्तराधिकारी कक्षा को कार्यान्वित करके आसानी से पर्याप्त कर सकते हैं जिसमें बेस स्ट्रीम के संदर्भ शामिल हैं और फिर रीड विधि को ओवरराइड कर रहे हैं। – Noldorin

उत्तर

37

टिप्पणी के अनुसार, यह स्पष्ट नहीं है कि विलय करके आपका क्या मतलब है।

या तो "यादृच्छिक रूप से" उपलब्ध इनपुट लेना InputStream.available द्वारा जटिल है जो आपको एक उपयोगी उत्तर और धाराओं के व्यवहार को अवरुद्ध करने के लिए आवश्यक नहीं है। आपको धाराओं से पढ़ने के लिए दो धागे की आवश्यकता होगी और फिर java.io.Piped(In|Out)putStream (हालांकि उन वर्गों में समस्याएं हैं) के माध्यम से डेटा वापस गुजरना होगा। वैकल्पिक रूप से कुछ प्रकार की धाराओं के लिए एक अलग इंटरफ़ेस का उपयोग करना संभव हो सकता है, उदाहरण के लिए java.nio गैर-अवरुद्ध चैनल।

यदि आप पहले इनपुट स्ट्रीम की पूर्ण सामग्री चाहते हैं तो दूसरे के बाद: new java.io.SequenceInputStream(s1, s2)

+2

ओह, बहुत अच्छा, मैंने अभी कुछ नया सीखा है। SequenceInputStream अनिवार्य रूप से मेरे CatInputStream के समान है, लेकिन एक लिंक्डलिस्ट के बजाए विरासत अंकन का उपयोग करना। :-) –

+0

आपके उत्तर के पहले हिस्से में एक हैक के रूप में, सामान्य मामले में हल करना मुश्किल है, लेकिन FileInputStream (और शायद सॉकेट भी) के विशिष्ट मामलों के लिए आप उदाहरण/कास्ट कर सकते हैं और इसमें से एक चैनल बना सकते हैं। (अन्य धाराएं एक सतत इंटरफ़ेस बनाने के लिए Channels.newChannel का उपयोग कर सकती हैं, लेकिन इसमें गैर-अवरुद्ध गुणों की आवश्यकता नहीं होगी।) –

+0

संग्रह। संज्ञान आपका मित्र है। मैं अपने पहले भाग का एक हिस्सा भूल गया - संपादित करेंगे। –

0

ऐसा नहीं है कि मैं सोच सकता हूं। आपको शायद दो धाराओं की सामग्री को बाइट [] में पढ़ना होगा और उसके बाद से बाइटएरेइन इनपुट स्ट्रीम बनाएं।

+0

एक सरल, समझने में आसान, व्यावहारिक समाधान के लिए उपरोक्त। ब्लॉकिंग महत्वपूर्ण है (या वे विशाल हैं) आवश्यक व्यवहार नहीं हो सकता है। –

4

आप एक कस्टम InputStream कार्यान्वयन लिख सकते हैं जो ऐसा करता है। उदाहरण:

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Collections; 
import java.util.Deque; 
import java.util.LinkedList; 

public class CatInputStream extends InputStream { 
    private final Deque<InputStream> streams; 

    public CatInputStream(InputStream... streams) { 
     this.streams = new LinkedList<InputStream>(); 
     Collections.addAll(this.streams, streams); 
    } 

    private void nextStream() throws IOException { 
     streams.removeFirst().close(); 
    } 

    @Override 
    public int read() throws IOException { 
     int result = -1; 
     while (!streams.isEmpty() 
       && (result = streams.getFirst().read()) == -1) { 
      nextStream(); 
     } 
     return result; 
    } 

    @Override 
    public int read(byte b[], int off, int len) throws IOException { 
     int result = -1; 
     while (!streams.isEmpty() 
       && (result = streams.getFirst().read(b, off, len)) == -1) { 
      nextStream(); 
     } 
     return result; 
    } 

    @Override 
    public long skip(long n) throws IOException { 
     long skipped = 0L; 
     while (skipped < n && !streams.isEmpty()) { 
      int thisSkip = streams.getFirst().skip(n - skipped); 
      if (thisSkip > 0) 
       skipped += thisSkip; 
      else 
       nextStream(); 
     } 
     return skipped; 
    } 

    @Override 
    public int available() throws IOException { 
     return streams.isEmpty() ? 0 : streams.getFirst().available(); 
    } 

    @Override 
    public void close() throws IOException { 
     while (!streams.isEmpty()) 
      nextStream(); 
    } 
} 

यह कोड परीक्षण नहीं किया गया है, इसलिए आपका लाभ भिन्न हो सकता है।

+0

क्या यह Merqubow द्वारा सुझाए गए अनुसार SequenceInputStream के समान नहीं है? –

+0

क्षमा करें, लेकिन tackline पहले SequenceInputStream का सुझाव दिया (और मैंने उसे उसके लिए +1 किया)। एसओ में, सबसे अच्छा अच्छा जवाब जीतता है; आप कभी नहीं जानते कि बाद के जवाब चोरी हैं या नहीं। साथ ही, SequenceInputStream और CatInputStream के बीच तुलना के लिए tackline के उत्तर पर मेरी टिप्पणी पढ़ें (मैं Collections.enumeration का उपयोग करने के बारे में अपना मुद्दा लेता हूं)। –

+0

यदि मेरे उत्तर को कम करने वाले व्यक्ति ने मेरी आखिरी टिप्पणी के कारण ऐसा किया, तो मैं क्षमा चाहता हूं; मुझे बेहतर समझा जाना चाहिए: यदि मैं एक उत्तर लिखता हूं जो पहले से पोस्ट किए गए उत्तर के डुप्लिकेट (या सबसेट) के रूप में सामने आता है, तो मैं आमतौर पर इसे हटा देता हूं, यह जानकर कि मुझे इसके लिए कोई भी अंक प्राप्त नहीं होगा। एसओ पर, यह वास्तव में "पश्चिम में सबसे तेज गन" है (उस प्रश्न शीर्षक के लिए खोजें)। –

14

java.io.SequenceInputStream आपको जो चाहिए वह हो सकता है। यह धाराओं की गणना स्वीकार करता है, और पहली धारा की सामग्री को आउटपुट करेगा, फिर दूसरा, और तब तक जब तक सभी धाराएं खाली न हों।

0

यहां बाइट एरे के लिए विशिष्ट एक एमवीआर कार्यान्वयन है (अपनी खुद की पैकेज परिभाषा को जोड़ना सुनिश्चित करें)। यहां से, मर्ज किए गए स्ट्रीम पर इनपुट स्ट्रीम लिखना तुच्छ है। अनुरोध किए जाने पर भी मैं उसे पोस्ट कर सकता हूं।

import java.nio.ByteBuffer; 

public final class MVar { 

    private static enum State { 
    EMPTY, ONE, MANY 
    } 

    private final Object lock; 

    private State state; 

    private byte b; 

    private ByteBuffer bytes; 
    private int length; 

    public MVar() { 
    lock = new Object(); 
    state = State.EMPTY; 
    } 

    public final void put(byte b) { 
    synchronized (lock) { 
     while (state != State.EMPTY) { 
     try { 
      lock.wait(); 
     } catch (InterruptedException e) {} 
     } 
     this.b = b; 
     state = State.ONE; 
     lock.notifyAll(); 
    } 
    } 

    public final void put(byte[] bytes, int offset, int length) { 
    if (length == 0) { 
     return; 
    } 
    synchronized (lock) { 
     while (state != State.EMPTY) { 
     try { 
      lock.wait(); 
     } catch (InterruptedException e) {} 
     } 
     this.bytes = ByteBuffer.allocateDirect(length); 
     this.bytes.put(bytes, offset, length); 
     this.bytes.position(0); 
     this.length = length; 
     state = State.MANY; 
     lock.notifyAll(); 
    } 
    } 

    public final byte take() { 
    synchronized (lock) { 
     while (state == State.EMPTY) { 
     try { 
      lock.wait(); 
     } catch (InterruptedException e) {} 
     } 
     switch (state) { 
     case ONE: { 
     state = State.EMPTY; 
     byte b = this.b; 
     lock.notifyAll(); 
     return b; 
     } 
     case MANY: { 
     byte b = bytes.get(); 
     state = --length <= 0 ? State.EMPTY : State.MANY; 
     lock.notifyAll(); 
     return b; 
     } 
     default: 
     throw new AssertionError(); 
     } 
    } 
    } 

    public final int take(byte[] bytes, int offset, int length) { 
    if (length == 0) { 
     return 0; 
    } 
    synchronized (lock) { 
     while (state == State.EMPTY) { 
     try { 
      lock.wait(); 
     } catch (InterruptedException e) {} 
     } 
     switch (state) { 
     case ONE: 
     bytes[offset] = b; 
     state = State.EMPTY; 
     lock.notifyAll(); 
     return 1; 
     case MANY: 
     if (this.length > length) { 
      this.bytes.get(bytes, offset, length); 
      this.length = this.length - length; 
      synchronized (lock) { 
      lock.notifyAll(); 
      } 
      return length; 
     } 
     this.bytes.get(bytes, offset, this.length); 
     this.bytes = null; 
     state = State.EMPTY; 
     length = this.length; 
     lock.notifyAll(); 
     return length; 
     default: 
     throw new AssertionError(); 
     } 
    } 
    } 
} 
संबंधित मुद्दे