How to Convert a Stream into a Byte[] in C#

How do I convert a Stream into a byte[] in C#?

Call next function like

byte[] m_Bytes = StreamHelper.ReadToEnd (mystream);

Function:

public static byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = 0;

if(stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}

try
{
byte[] readBuffer = new byte[4096];

int totalBytesRead = 0;
int bytesRead;

while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;

if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}

byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if(stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}

Creating a byte array from a stream

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).

c# convert system.IO.Stream to Byte[]

If you are reading a file just use the File.ReadAllBytes Method:

byte[] myBinary = File.ReadAllBytes(@"C:\MyDir\MyFile.bin");

Also, there is no need to CopyTo a MemoryStream just to get a byte array as long as your sourceStream supports the Length property:

byte[] myBinary = new byte[paramFile.Length];
paramFile.Read(myBinary, 0, (int)paramFile.Length);

Superimpose a stream on top of a byte array

The MemoryStream constructor you mentioned in the second block actually does what you want. It saves the array you provide and uses that as the backing buffer for the stream. You can modify the array and those changes will be reflected by the stream if those bytes are still yet to be read.

Here's a minimal reproducible example to demonstrate this.

byte[] source = new byte[] { 0, 1, 2, 3 };
MemoryStream stream = new MemoryStream(source);

// If the constructor made a copy, the stream won't be
// affected and it will output 0 below.
source[0] = 10;

byte b = (byte)stream.ReadByte();

Console.WriteLine(b);

Output:

10

Try it out!

Be aware that the stream cannot grow when you use that constructor. According to its documentation:

The length of the stream cannot be set to a value greater than the initial length of the specified byte array; however, the stream can be truncated (see SetLength).

Allowing it to grow would break the expectation that it's using that buffer because growing would require allocating a new array and copying the data to it.

Convert Stream from file in archive to Byte[]

Try to do something like this:

using (ZipArchive archive = ZipFile.OpenRead("archieve.zip")) 
{

foreach (ZipArchiveEntry entry in archive.Entries)
{
using (Stream stream = entry.Open())
{
byte[] bytes;
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
bytes = ms.ToArray();
}
}
}
}


Related Topics



Leave a reply



Submit