c# एक धारा से एक बाइट सरणी बनाना




बिट क्या है? (9)

मुझे बॉब (यानी प्रश्नकर्ता) कोड के साथ संकलन समय त्रुटि मिलती है। Stream.Length एक लंबा है जबकि BinaryReader.ReadBytes एक पूर्णांक पैरामीटर लेता है। मेरे मामले में, मुझे लंबी परिशुद्धता की आवश्यकता के लिए पर्याप्त धाराओं से निपटने की उम्मीद नहीं है, इसलिए मैं निम्न का उपयोग करता हूं:

Stream s;
byte[] b;

if (s.Length > int.MaxValue) {
  throw new Exception("This stream is larger than the conversion algorithm can currently handle.");
}

using (var br = new BinaryReader(s)) {
  b = br.ReadBytes((int)s.Length);
}

इनपुट स्ट्रीम से बाइट सरणी बनाने के लिए पसंदीदा विधि क्या है?

.NET 3.5 के साथ मेरा वर्तमान समाधान यहां है।

Stream s;
byte[] b;

using (BinaryReader br = new BinaryReader(s))
{
    b = br.ReadBytes((int)s.Length);
}

क्या स्ट्रीम के हिस्सों को पढ़ने और लिखना अभी भी एक बेहतर विचार है?


MemoryStream ms = new MemoryStream();
file.PostedFile.InputStream.CopyTo(ms);
var byts = ms.ToArray();
ms.Dispose();

public static byte[] ToByteArray(Stream stream)
    {
        if (stream is MemoryStream)
        {
            return ((MemoryStream)stream).ToArray();
        }
        else
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }            
    }

आप एक्सटेंशन के साथ इसे फैनसीयर भी बना सकते हैं:

namespace Foo
{
    public static class Extensions
    {
        public static byte[] ToByteArray(this Stream stream)
        {
            using (stream)
            {
                using (MemoryStream memStream = new MemoryStream())
                {
                     stream.CopyTo(memStream);
                     return memStream.ToArray();
                }
            }
        }
    }
}

और फिर इसे नियमित विधि के रूप में कॉल करें:

byte[] arr = someStream.ToByteArray()

जबकि जॉन का जवाब सही है, वह कोड लिख रहा है जो पहले से ही CopyTo में मौजूद है। तो .Net 4 के लिए संदीप के समाधान का उपयोग करें, लेकिन नेट के पिछले संस्करण के लिए जॉन के जवाब का उपयोग करें। सिपिप के कोड को "उपयोग" के उपयोग से बेहतर किया जाएगा क्योंकि कॉपीटो में अपवाद हैं, कई स्थितियों में, काफी संभावना है और मेमोरीस्ट्रीम को डिस्पोजेक्ट नहीं छोड़ देगा।

public static byte[] ReadFully(Stream input)
{
    using (MemoryStream ms = new MemoryStream())
    {
        input.CopyTo(ms);
        return ms.ToArray();
    }
}

मैं इसे एक पंक्ति पर काम करने में सक्षम था:

byte [] byteArr= ((MemoryStream)localStream).ToArray();

जैसा कि johnnyRose द्वारा स्पष्ट किया गया है, ऊपर कोड केवल johnnyRose लिए काम करेगा


उपर्युक्त एक ठीक है ... लेकिन जब आप एसएमटीपी पर सामान भेजते हैं तो आपको डेटा भ्रष्टाचार का सामना करना पड़ेगा (यदि आपको आवश्यकता है)। मैंने कुछ और बदल दिया है जो बाइट के लिए बाइट को सही ढंग से भेजने में मदद करेगा: '

using System;
using System.IO;

        private static byte[] ReadFully(string input)
        {
            FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer
            BinaryReader binReader = new BinaryReader(sourceFile);
            byte[] output = new byte[sourceFile.Length]; //create byte array of size file
            for (long i = 0; i < sourceFile.Length; i++)
                output[i] = binReader.ReadByte(); //read until done
            sourceFile.Close(); //dispose streamer
            binReader.Close(); //dispose reader
            return output;
        }'

बस मेरे जोड़े सेंट ... मैं जिस अभ्यास का अक्सर उपयोग करता हूं वह इस तरह के तरीकों को एक कस्टम सहायक के रूप में व्यवस्थित करना है

public static class StreamHelpers
{
    public static byte[] ReadFully(this Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
}

कॉन्फ़िगरेशन फ़ाइल में नेमस्पेस जोड़ें और अपनी इच्छानुसार कहीं भी इसका उपयोग करें


यह वास्तव में इस पर निर्भर करता है कि आप s.Lengths.Length भरोसा कर सकते हैं या नहीं। कई धाराओं के लिए, आप नहीं जानते कि कितना डेटा होगा। ऐसे मामलों में - और .NET 4 से पहले - मैं इस तरह के कोड का उपयोग करता हूं:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

.NET 4 और ऊपर के साथ, मैं Stream.CopyTo उपयोग करता Stream.CopyTo , जो मूल रूप से मेरे कोड में लूप के बराबर है - stream.CopyTo(ms) बनाएं, कॉल stream.CopyTo(ms) करें। stream.CopyTo(ms) और फिर ms.ToArray() वापस करें। काम हो गया।

मुझे शायद यह समझाया जाना चाहिए कि मेरा जवाब दूसरों की तुलना में लंबा क्यों है। Stream.Read गारंटी नहीं देता है कि यह सब कुछ जो उसने मांगा है उसे पढ़ेगा। यदि आप किसी नेटवर्क स्ट्रीम से पढ़ रहे हैं, उदाहरण के लिए, यह एक पैकेट के लायक को पढ़ सकता है और फिर वापस लौटा सकता है, भले ही अधिक डेटा जल्द ही हो। BinaryReader.Read स्ट्रीम के अंत तक या आपके निर्दिष्ट आकार तक जारी रहेगा, लेकिन आपको अभी भी आकार के साथ शुरू करना होगा।

उपरोक्त विधि डेटा को तब तक पढ़ेगी (और मेमोरीस्ट्रीम में कॉपी करना) जब तक यह डेटा से बाहर नहीं हो जाती। इसके बाद मेमोरीस्ट्रीम को एक सरणी में डेटा की प्रतिलिपि वापस करने के लिए कहा जाता है। यदि आप आकार के साथ शुरू करने के बारे में जानते हैं - या लगता है कि आप आकार के बारे में सोचते हैं, तो सुनिश्चित किए बिना - आप मेमोरीस्ट्रीम को उस आकार के साथ शुरू करने के लिए बना सकते हैं। इसी तरह आप अंत में एक चेक डाल सकते हैं, और यदि स्ट्रीम की लंबाई बफर के समान आकार ( MemoryStream.GetBuffer द्वारा लौटाई गई) है तो आप बस बफर वापस कर सकते हैं। तो उपर्युक्त कोड काफी अनुकूलित नहीं है, लेकिन कम से कम सही होगा। यह धारा बंद करने के लिए कोई ज़िम्मेदारी नहीं लेता है - कॉलर को ऐसा करना चाहिए।

अधिक जानकारी के लिए यह आलेख देखें (और एक वैकल्पिक कार्यान्वयन)।





inputstream