c# - मैं एक स्ट्रीम की सामग्री को दूसरे में कैसे कॉपी करूं?




stream copying (8)

एक स्ट्रीम की सामग्री को दूसरे में कॉपी करने का सबसे अच्छा तरीका क्या है? क्या इसके लिए एक मानक उपयोगिता विधि है?


"कॉपीस्ट्रीम" के कार्यान्वयन को अलग करने वाले बुनियादी प्रश्न हैं:

  • रीडिंग बफर का आकार
  • लिखने का आकार
  • क्या हम एक से अधिक धागे का उपयोग कर सकते हैं (लिखते समय लिखना)।

इन सवालों के जवाब के परिणामस्वरूप कॉपीस्ट्रीम के काफी अलग-अलग कार्यान्वयन होते हैं और यह निर्भर करता है कि आपके पास किस तरह की धाराएं हैं और आप अनुकूलित करने का प्रयास कर रहे हैं। "सर्वश्रेष्ठ" कार्यान्वयन को यह जानने की भी आवश्यकता होगी कि स्ट्रीम किस विशिष्ट हार्डवेयर को पढ़ रहे थे और लिख रहे थे।


.NET 3.5 के लिए और कोशिश करने से पहले:

MemoryStream1.WriteTo(MemoryStream2);

आप किस प्रकार की स्ट्रीम के साथ काम कर रहे हैं इस पर निर्भर करते हुए, इसे और अधिक कुशलता से करने का एक तरीका हो सकता है। यदि आप अपनी एक या दोनों धाराओं को मेमोरीस्ट्रीम में परिवर्तित कर सकते हैं, तो आप अपने डेटा का प्रतिनिधित्व करने वाले बाइट सरणी के साथ सीधे काम करने के लिए GetBuffer विधि का उपयोग कर सकते हैं। यह आपको Array.CopyTo जैसी विधियों का उपयोग करने देता है, जो fryguybob द्वारा उठाए गए सभी मुद्दों को दूर करते हैं। डेटा की प्रतिलिपि बनाने के इष्टतम तरीके से जानने के लिए आप .NET पर भरोसा कर सकते हैं।


आसान और सुरक्षित - मूल स्रोत से नई स्ट्रीम बनाएं:

    MemoryStream source = new MemoryStream(byteArray);
    MemoryStream copy = new MemoryStream(byteArray);

दुर्भाग्य से, वास्तव में कोई आसान समाधान नहीं है। आप ऐसा कुछ कोशिश कर सकते हैं:

Stream s1, s2;
byte[] buffer = new byte[4096];
int bytesRead = 0;
while (bytesRead = s1.Read(buffer, 0, buffer.Length) > 0) s2.Write(buffer, 0, bytesRead);
s1.Close(); s2.Close();

लेकिन अगर स्ट्रीम पढ़ने के लिए कुछ भी नहीं है तो स्ट्रीम क्लास के अलग-अलग कार्यान्वयन के साथ समस्या अलग-अलग व्यवहार कर सकती है। एक स्थानीय हार्डड्राइव से फ़ाइल पढ़ने वाली स्ट्रीम शायद तब तक अवरुद्ध हो जाएगी जब तक कि पढ़ने वाले ऑपरेशन ने डिस्क से पर्याप्त डेटा को बफर भरने के लिए नहीं पढ़ा है और फ़ाइल के अंत तक पहुंचने पर केवल कम डेटा लौटाता है। दूसरी तरफ, नेटवर्क से पढ़ने वाली धारा कम डेटा लौटा सकती है, भले ही अधिक डेटा प्राप्त किया जा सके।

जेनेरिक समाधान का उपयोग करने से पहले आप जिस विशिष्ट स्ट्रीम क्लास का उपयोग कर रहे हैं उसका दस्तावेज़ीकरण हमेशा जांचें।


मेमोरीस्ट्रीम में है। राइटो (आउटस्ट्रीम);

और .NET 4.0 में सामान्य स्ट्रीम ऑब्जेक्ट पर कॉपी करें।

.NET 4.0:

instream.CopyTo(outstream);

यदि आप एक धारा को प्रतिलिपि बनाने के लिए एक प्रसंस्करण चाहते हैं जो कि पोस्ट की गई है, ठीक है लेकिन यह स्थिति रीसेट नहीं है, यह होना चाहिए

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    long TempPos = input.Position;
    while (true)    
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
    }
    input.Position = TempPos;// or you make Position = 0 to set it at the start
}

लेकिन यदि यह रनटाइम में है, तो उस प्रक्रिया का उपयोग न करें जिसे आप स्मृति स्ट्रीम का उपयोग करते हैं

Stream output = new MemoryStream();
byte[] buffer = new byte[32768]; // or you specify the size you want of your buffer
long TempPos = input.Position;
while (true)    
{
    int read = input.Read (buffer, 0, buffer.Length);
    if (read <= 0)
        return;
    output.Write (buffer, 0, read);
 }
    input.Position = TempPos;// or you make Position = 0 to set it at the start

वास्तव में, स्ट्रीम कॉपी करने का एक कम भारी हाथ है। हालांकि ध्यान दें, इसका मतलब यह है कि आप पूरी फ़ाइल को स्मृति में संग्रहीत कर सकते हैं। कोशिश न करें और इसका उपयोग करें यदि आप सैकड़ों मेगाबाइट्स या उससे अधिक फ़ाइलों में काम कर रहे हैं, बिना सावधानी के।

public static void CopyStream(Stream input, Stream output)
{
  using (StreamReader reader = new StreamReader(input))
  using (StreamWriter writer = new StreamWriter(output))
  {
    writer.Write(reader.ReadToEnd());
  }
}

नोट: बाइनरी डेटा और वर्ण एन्कोडिंग से संबंधित कुछ समस्याएं भी हो सकती हैं।





copying