Creating a byte array from a stream

后端 未结 16 2947
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-21 23:22

What is the prefered method for creating a byte array from an input stream?

Here is my current solution with .NET 3.5.

Stream s;
byte[] b;

using (         


        
相关标签:
16条回答
  • 2020-11-21 23:38

    While Jon's answer is correct, he is rewriting code that already exists in CopyTo. So for .Net 4 use Sandip's solution, but for previous version of .Net use Jon's answer. Sandip's code would be improved by use of "using" as exceptions in CopyTo are, in many situations, quite likely and would leave the MemoryStream not disposed.

    public static byte[] ReadFully(Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }
    
    0 讨论(0)
  • 2020-11-21 23:45

    Create a helper class and reference it anywhere you wish to use it.

    public static class StreamHelpers
    {
        public static byte[] ReadFully(this Stream input)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 23:48

    It really depends on whether or not you can trust s.Length. For many streams, you just don't know how much data there will be. In such cases - and before .NET 4 - I'd use code like this:

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

    With .NET 4 and above, I'd use Stream.CopyTo, which is basically equivalent to the loop in my code - create the MemoryStream, call stream.CopyTo(ms) and then return ms.ToArray(). Job done.

    I should perhaps explain why my answer is longer than the others. Stream.Read doesn't guarantee that it will read everything it's asked for. If you're reading from a network stream, for example, it may read one packet's worth and then return, even if there will be more data soon. BinaryReader.Read will keep going until the end of the stream or your specified size, but you still have to know the size to start with.

    The above method will keep reading (and copying into a MemoryStream) until it runs out of data. It then asks the MemoryStream to return a copy of the data in an array. If you know the size to start with - or think you know the size, without being sure - you can construct the MemoryStream to be that size to start with. Likewise you can put a check at the end, and if the length of the stream is the same size as the buffer (returned by MemoryStream.GetBuffer) then you can just return the buffer. So the above code isn't quite optimised, but will at least be correct. It doesn't assume any responsibility for closing the stream - the caller should do that.

    See this article for more info (and an alternative implementation).

    0 讨论(0)
  • 2020-11-21 23:49

    You can simply use ToArray() method of MemoryStream class, for ex-

    MemoryStream ms = (MemoryStream)dataInStream;
    byte[] imageBytes = ms.ToArray();
    
    0 讨论(0)
  • 2020-11-21 23:49
    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();
                }
            }            
        }
    
    0 讨论(0)
  • 2020-11-21 23:50

    You can even make it fancier with extensions:

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

    And then call it as a regular method:

    byte[] arr = someStream.ToByteArray()
    
    0 讨论(0)
提交回复
热议问题