Is there a simple way or method to convert a Stream
into a byte[]
in C#?

- 3,329
- 3
- 29
- 49

- 279,434
- 135
- 377
- 622
-
6Not really the answer to the question but if your Stream comes from a file you can use `File.ReadAllBytes(path)` to get the bytes array in one line. – Jesus Jimenez Jun 18 '12 at 13:15
-
@JesusJimenez you save me a lot of time of implementation, I know than has pass a lot of time from your answer but thanks a lot – sgrysoft Jul 11 '22 at 13:14
12 Answers
The shortest solution I know:
using(var memoryStream = new MemoryStream())
{
sourceStream.CopyTo(memoryStream);
return memoryStream.ToArray();
}

- 10,581
- 2
- 14
- 4
-
76
-
-
9Yes it does. You could use MemoryStream.GetBuffer() to avoid the extra copy but beware that the size of the array returned is not the size of the data. – James Dingle Apr 30 '12 at 03:25
-
4If the length of the source stream is known upfront, it is better to specify the capacity of the MemoryStream with this length; the internal buffer will have the proper size. If the length is not known, then writing to MemoryStream implies potential multiple copies of the internal buffer as the data is written and the buffer extended, and in that case the extra copy of ToArray is not necessarily the main problem. – James Dingle Apr 30 '12 at 03:46
-
16`MemoryStream` is `IDisposable` - shouldn't it be wrapped in a `using`? – BlueRaja - Danny Pflughoeft May 27 '13 at 21:23
-
4Corrected. There is no real need in the case of MemoryStream (dig in the source code, it does nothing), but this could change. – James Dingle Jul 01 '13 at 06:29
-
1CopyToAsync can be used to do the call async. The method is available since .Net framework 4.5. – Valderann Aug 12 '17 at 07:53
-
Another fun note is that `memoryStream.ToArray()` is available even after the `memoryStream` is disposed. – Sam Rueby Oct 10 '19 at 19:32
-
@JamesDingle -- in this case it's probably fine if you know the size up front, since you're only using it to dump those bytes in and spit them back out -- but for general usage, avoid using the constructor parameters in memory streams -- they can have really gnarly (and unexpected) side effects (e.g. if you specify a byte array your memory stream can't grow beyond the original size). – BrainSlugs83 Nov 12 '20 at 22:46
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;
}
}
}

- 28,442
- 25
- 137
- 286

- 16,354
- 10
- 36
- 43
-
22Not sure I'd agree with the Length*2 buffer expansion policy there. – Remus Rusanu Jul 03 '09 at 18:48
-
Yes its true. But i use this code in frameworks 1.1 and 2.0. Because this is so big. Your answer is good to. – pedrofernandes Jul 03 '09 at 18:48
-
2If you want to be able to read streams of arbitrary length, pretty much all of that is needed. You could use a List
and save some code.. – Thorarin Jul 03 '09 at 18:50 -
3A bunch of concerns are mixed together in one big method. Yes, it all has to be done, but not all in one function. There's the growable byte array and there's the stream reading. Much easier to get right if they're separated. – Daniel Earwicker Jul 03 '09 at 18:57
-
2That code could be made much simpler by using a MemoryStream... – Thomas Levesque Jul 03 '09 at 19:09
-
@Thomas - indeed, see my answer - the only custom code you need to write is a stream copy function that can then be reused for copying a stream directly to any other stream. – Daniel Earwicker Jul 03 '09 at 19:14
-
1Looks like a modified version of http://www.yoda.arachsys.com/csharp/readbinary.html – SwDevMan81 Jul 06 '09 at 03:45
-
This code example doesn't consider streams that are not seekable. Setting stream.Position should only be done when stream.CanSeek is true. – Matt Z Jul 08 '10 at 08:13
I use this extension class:
public static class StreamExtensions
{
public static byte[] ReadAllBytes(this Stream instream)
{
if (instream is MemoryStream)
return ((MemoryStream) instream).ToArray();
using (var memoryStream = new MemoryStream())
{
instream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
}
Just copy the class to your solution and you can use it on every stream:
byte[] bytes = myStream.ReadAllBytes()
Works great for all my streams and saves a lot of code! Of course you can modify this method to use some of the other approaches here to improve performance if needed, but I like to keep it simple.

- 3,361
- 32
- 25
-
if (instream is MemoryStream) return ((MemoryStream) instream).ToArray(); Changed to: var ms = instream as MemoryStream; if (ms != null) return ms.ToArray(); – Garry Xiao Jan 06 '20 at 08:51
-
9Even better with C# 7: `if (instream is MemoryStream memoryStream) return memoryStream.ToArray();` – JCH2k Jan 06 '20 at 13:53
In .NET Framework 4 and later, the Stream
class has a built-in CopyTo
method that you can use.
For earlier versions of the framework, the handy helper function to have is:
public static void CopyStream(Stream input, Stream output)
{
byte[] b = new byte[32768];
int r;
while ((r = input.Read(b, 0, b.Length)) > 0)
output.Write(b, 0, r);
}
Then use one of the above methods to copy to a MemoryStream
and call GetBuffer
on it:
var file = new FileStream("c:\\foo.txt", FileMode.Open);
var mem = new MemoryStream();
// If using .NET 4 or later:
file.CopyTo(mem);
// Otherwise:
CopyStream(file, mem);
// getting the internal buffer (no additional copying)
byte[] buffer = mem.GetBuffer();
long length = mem.Length; // the actual length of the data
// (the array may be longer)
// if you need the array to be exactly as long as the data
byte[] truncated = mem.ToArray(); // makes another copy
Edit: originally I suggested using Jason's answer for a Stream
that supports the Length
property. But it had a flaw because it assumed that the Stream
would return all its contents in a single Read
, which is not necessarily true (not for a Socket
, for example.) I don't know if there is an example of a Stream
implementation in the BCL that does support Length
but might return the data in shorter chunks than you request, but as anyone can inherit Stream
this could easily be the case.
It's probably simpler for most cases to use the above general solution, but supposing you did want to read directly into an array that is bigEnough
:
byte[] b = new byte[bigEnough];
int r, offset;
while ((r = input.Read(b, offset, b.Length - offset)) > 0)
offset += r;
That is, repeatedly call Read
and move the position you will be storing the data at.

- 114,894
- 38
- 205
- 284
-
Why bother with memorystream when you could just use a List
and AddRange()? It's doing exactly the same anyway under the hood as far as I know. – Tamas Czinege Jul 04 '09 at 00:17 -
@DrJokepu - because stream-to-stream copying is generally useful in other situations. You only have to write that one method, and you get stream-to-stream copying and stream-to-array copying. – Daniel Earwicker Jul 04 '09 at 07:01
-
1@John Saunders - that CopyStream method definitely shouldn't have using statements in it, so that would have been an odd request. The example usage might need one on the FileStream - but it might not (depends whether the rest of the code wants to reuse the same FileStream somehow). – Daniel Earwicker Jul 04 '09 at 07:04
-
As I just got an upvote on this out of the blue, I noticed it is overdue for an update as `Stream` now has a `CopyTo` method that does exactly what the `CopyStream` did. – Daniel Earwicker Feb 10 '15 at 16:41
Byte[] Content = new BinaryReader(file.InputStream).ReadBytes(file.ContentLength);

- 2,886
- 4
- 24
- 37

- 521
- 5
- 4
-
I could be wrong, but this seems to be more efficient than the MemoryStream way that creates two copies in memory. – Dan Randolph Jun 20 '16 at 20:42
-
1Depends on the scenario, your example is very specific to the file stream which you can determine the content length. What about if the input is a stream? as Readbytes only accepts the int32 – Vincent Feb 20 '17 at 00:00
-
2
byte[] buf; // byte array
Stream stream=Page.Request.InputStream; //initialise new stream
buf = new byte[stream.Length]; //declare arraysize
stream.Read(buf, 0, buf.Length); // read from stream to byte array

- 364
- 3
- 6
-
5If I recall correctly "Read" doesn't always read the entire available amount from the stream - eg request N bytes, return M bytes with M < N. Hence the various methods to build a buffer and read a number of times. https://msdn.microsoft.com/en-us/library/system.io.stream.read(v=vs.110).aspx – David Ford Jun 30 '16 at 04:22
-
You can't be sure that you can call `Stream.Length` - it might throw an exception. – Ykok Mar 29 '23 at 12:22
Ok, maybe I'm missing something here, but this is the way I do it:
public static Byte[] ToByteArray(this Stream stream) {
Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length);
Byte[] buffer = new Byte[length];
stream.Read(buffer, 0, length);
return buffer;
}

- 7,310
- 17
- 40
- 61

- 1,601
- 19
- 19
-
For this method and @user734862's method I got the following error: 'This stream does not support seek operations' a System.NotSupportedException. I think this may be down to the fact that I'm reading a file from a http location and then sending it back. It may well be different for when you are working with a file on your system. – Daniel Hollinrake Mar 01 '13 at 01:14
-
Stream.Read method can read less bytes than you request. You should check return value of Read method. – arkhivania Mar 04 '13 at 08:33
-
1The stream returned from, e.g., Microsoft.SharePoint.Client.File.OpenBinaryDirect very often returns only 500 or so bytes at a time, no matter how big your buffer is. You should never ignore the return value of Stream.Read. – Dylan Nicholson Nov 15 '13 at 00:20
-
But look closely to the code. The buffer is created based on stream.Length information. It will never be too big for the stream. It may be too small (Int32.MaxValue is the maximum size for it), but this is very unlikely to happen in most cases. – Vinicius Jun 20 '14 at 05:24
-
3Ths problem is that Stream.Read doesn't always read `length` bytes - it can decide to read less (and returns the actual number of bytes read). You *have* to call this in a loop to make it work universally! – JCH2k Nov 09 '17 at 16:43
if you post a file from mobile device or other
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}

- 4,083
- 3
- 46
- 54
-
Should mention that you can actually use this on any FileStream. In WPF, you can't use `Request.Files[0].InputStream`, but you can do `using (FileStream fs = new File.OpenRead(fileName)) { var binaryReader = new BinaryReader(fs); fileData = binaryReader.ReadBytes((int)fs.Length); }`. Thanks for the tip! – vapcguy Oct 11 '16 at 23:19
Stream s;
int len = (int)s.Length;
byte[] b = new byte[len];
int pos = 0;
while((r = s.Read(b, pos, len - pos)) > 0) {
pos += r;
}
A slightly more complicated solution is necesary is s.Length
exceeds Int32.MaxValue
. But if you need to read a stream that large into memory, you might want to think about a different approach to your problem.
Edit: If your stream does not support the Length
property, modify using Earwicker's workaround.
public static class StreamExtensions {
// Credit to Earwicker
public static void CopyStream(this Stream input, Stream output) {
byte[] b = new byte[32768];
int r;
while ((r = input.Read(b, 0, b.Length)) > 0) {
output.Write(b, 0, r);
}
}
}
[...]
Stream s;
MemoryStream ms = new MemoryStream();
s.CopyStream(ms);
byte[] b = ms.GetBuffer();
-
-
He did say read. He wanted to convert the stream into byte[], which is a Read, not a Write. – John Saunders Jul 03 '09 at 19:27
-
Another problem with this (I've just remembered) is that the Read method may not return all the data in one go. – Daniel Earwicker Jul 03 '09 at 21:13
You could also try just reading in parts at a time and expanding the byte array being returned:
public byte[] StreamToByteArray(string fileName)
{
byte[] total_stream = new byte[0];
using (Stream input = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
byte[] stream_array = new byte[0];
// Setup whatever read size you want (small here for testing)
byte[] buffer = new byte[32];// * 1024];
int read = 0;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
stream_array = new byte[total_stream.Length + read];
total_stream.CopyTo(stream_array, 0);
Array.Copy(buffer, 0, stream_array, total_stream.Length, read);
total_stream = stream_array;
}
}
return total_stream;
}

- 48,814
- 22
- 151
- 184
"bigEnough" array is a bit of a stretch. Sure, buffer needs to be "big ebough" but proper design of an application should include transactions and delimiters. In this configuration each transaction would have a preset length thus your array would anticipate certain number of bytes and insert it into correctly sized buffer. Delimiters would ensure transaction integrity and would be supplied within each transaction. To make your application even better, you could use 2 channels (2 sockets). One would communicate fixed length control message transactions that would include information about size and sequence number of data transaction to be transferred using data channel. Receiver would acknowledge buffer creation and only then data would be sent. If you have no control over stream sender than you need multidimensional array as a buffer. Component arrays would be small enough to be manageable and big enough to be practical based on your estimate of expected data. Process logic would seek known start delimiters and then ending delimiter in subsequent element arrays. Once ending delimiter is found, new buffer would be created to store relevant data between delimiters and initial buffer would have to be restructured to allow data disposal.
As far as a code to convert stream into byte array is one below.
Stream s = yourStream;
int streamEnd = Convert.ToInt32(s.Length);
byte[] buffer = new byte[streamEnd];
s.Read(buffer, 0, streamEnd);

- 1,157
- 5
- 17
- 31
-
1same as every other answer: never do stream.Read() without checking the return value of how many it has actually read... – Bernhard Jul 09 '20 at 05:36
Quick and dirty technique:
static byte[] StreamToByteArray(Stream inputStream)
{
if (!inputStream.CanRead)
{
throw new ArgumentException();
}
// This is optional
if (inputStream.CanSeek)
{
inputStream.Seek(0, SeekOrigin.Begin);
}
byte[] output = new byte[inputStream.Length];
int bytesRead = inputStream.Read(output, 0, output.Length);
Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length");
return output;
}
Test:
static void Main(string[] args)
{
byte[] data;
string path = @"C:\Windows\System32\notepad.exe";
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
data = StreamToByteArray(fs);
}
Debug.Assert(data.Length > 0);
Debug.Assert(new FileInfo(path).Length == data.Length);
}
I would ask, why do you want to read a stream into a byte[], if you are wishing to copy the contents of a stream, may I suggest using MemoryStream and writing your input stream into a memory stream.

- 2,283
- 20
- 22
-
4
-
3There's absolutely no guarantee that Read() returns all bytes to be read. – Stefan Schultze Dec 03 '09 at 12:22