How to get a MemoryStream from a Stream in .NET?
Asked Answered
P

9

100

I have the following constructor method which opens a MemoryStream from a file path:

MemoryStream _ms;

public MyClass(string filePath)
{
    byte[] docBytes = File.ReadAllBytes(filePath);
    _ms = new MemoryStream();
    _ms.Write(docBytes, 0, docBytes.Length);
}

I need to change this to accept a Stream instead of a file path. Whats the easiest/most efficient way to get a MemoryStream from the Stream object?

Pasteboard answered 9/7, 2010 at 12:51 Comment(3)
Once you have the Stream, why bother converting it to a MemoryStream? Can't you just work with the Stream directly?Lacuna
I need a MemoryStream due to other dependencies.Pasteboard
There are also instances where poor performance working with Streams causes a MemoryStream to be more efficient. Like my question here: #50399981Countermine
L
34

If you're modifying your class to accept a Stream instead of a filename, don't bother converting to a MemoryStream. Let the underlying Stream handle the operations:

public class MyClass
{ 
    Stream _s;

    public MyClass(Stream s) { _s = s; }
}

But if you really need a MemoryStream for internal operations, you'll have to copy the data out of the source Stream into the MemoryStream:

public MyClass(Stream stream)
{
    _ms = new MemoryStream();
    CopyStream(stream, _ms);
}

// Merged From linked CopyStream below and Jon Skeet's ReadFully example
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[16*1024];
    int read;
    while((read = input.Read (buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}
Lacuna answered 9/7, 2010 at 12:58 Comment(4)
I'm presuming that's > 0 at the end of the while line?Pasteboard
@Pasteboard - Correct. I got a little delete happy. Fixed.Lacuna
looks like one closing parenthesis is missing. should be while((read = input.Read(buffer,0,buffer.Length)) > 0)Useless
Might want to add output.Position = 0; as the very last line otherwise you'll need to remember to reset it later.Aeromedical
P
245

In .NET 4, you can use Stream.CopyTo to copy a stream, instead of the home-brew methods listed in the other answers.

MemoryStream _ms;
    
public MyClass(Stream sourceStream)
{
    _ms = new MemoryStream();
    sourceStream.CopyTo(_ms);
}
Pulitzer answered 9/7, 2010 at 13:24 Comment(2)
Make sure you first set sourceStream.Position = 0;Ointment
You will need to set _ms.Position = 0; prior to using it as well.Abolition
V
69

Use this:

var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);

This will convert Stream to MemoryStream.

Vigen answered 28/9, 2015 at 10:7 Comment(0)
L
34

If you're modifying your class to accept a Stream instead of a filename, don't bother converting to a MemoryStream. Let the underlying Stream handle the operations:

public class MyClass
{ 
    Stream _s;

    public MyClass(Stream s) { _s = s; }
}

But if you really need a MemoryStream for internal operations, you'll have to copy the data out of the source Stream into the MemoryStream:

public MyClass(Stream stream)
{
    _ms = new MemoryStream();
    CopyStream(stream, _ms);
}

// Merged From linked CopyStream below and Jon Skeet's ReadFully example
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[16*1024];
    int read;
    while((read = input.Read (buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}
Lacuna answered 9/7, 2010 at 12:58 Comment(4)
I'm presuming that's > 0 at the end of the while line?Pasteboard
@Pasteboard - Correct. I got a little delete happy. Fixed.Lacuna
looks like one closing parenthesis is missing. should be while((read = input.Read(buffer,0,buffer.Length)) > 0)Useless
Might want to add output.Position = 0; as the very last line otherwise you'll need to remember to reset it later.Aeromedical
L
5

You can simply do:

var ms = new MemoryStream(File.ReadAllBytes(filePath));

Stream position is 0 and ready to use.

Lahr answered 2/11, 2018 at 11:23 Comment(2)
This is the cleanest and most elegant solution.Genitourinary
This doesn't answer the question at all!Piggin
M
3

You will have to read in all the data from the Stream object into a byte[] buffer and then pass that into the MemoryStream via its constructor. It may be better to be more specific about the type of stream object you are using. Stream is very generic and may not implement the Length attribute, which is rather useful when reading in data.

Here's some code for you:

public MyClass(Stream inputStream) {
    byte[] inputBuffer = new byte[inputStream.Length];
    inputStream.Read(inputBuffer, 0, inputBuffer.Length);

    _ms = new MemoryStream(inputBuffer);
}

If the Stream object doesn't implement the Length attribute, you will have to implement something like this:

public MyClass(Stream inputStream) {
    MemoryStream outputStream = new MemoryStream();

    byte[] inputBuffer = new byte[65535];
    int readAmount;
    while((readAmount = inputStream.Read(inputBuffer, 0, inputBuffer.Length)) > 0)
        outputStream.Write(inputBuffer, 0, readAmount);

    _ms = outputStream;
}
Mcneese answered 9/7, 2010 at 13:1 Comment(0)
B
3

I use this combination of extension methods:

    public static Stream Copy(this Stream source)
    {
        if (source == null)
            return null;

        long originalPosition = -1;

        if (source.CanSeek)
            originalPosition = source.Position;

        MemoryStream ms = new MemoryStream();

        try
        {
            Copy(source, ms);

            if (originalPosition > -1)
                ms.Seek(originalPosition, SeekOrigin.Begin);
            else
                ms.Seek(0, SeekOrigin.Begin);

            return ms;
        }
        catch
        {
            ms.Dispose();
            throw;
        }
    }

    public static void Copy(this Stream source, Stream target)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (target == null)
            throw new ArgumentNullException("target");

        long originalSourcePosition = -1;
        int count = 0;
        byte[] buffer = new byte[0x1000];

        if (source.CanSeek)
        {
            originalSourcePosition = source.Position;
            source.Seek(0, SeekOrigin.Begin);
        }

        while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
            target.Write(buffer, 0, count);

        if (originalSourcePosition > -1)
        {
            source.Seek(originalSourcePosition, SeekOrigin.Begin);
        }
    }
Blanchette answered 9/7, 2010 at 13:10 Comment(0)
B
2

How do I copy the contents of one stream to another?

see that. accept a stream and copy to memory. you should not use .Length for just Stream because it is not necessarily implemented in every concrete Stream.

Burnedout answered 9/7, 2010 at 12:57 Comment(0)
I
2
public static void Do(Stream in)
{
    _ms = new MemoryStream();
    byte[] buffer = new byte[65536];
    while ((int read = input.Read(buffer, 0, buffer.Length))>=0)
        _ms.Write (buffer, 0, read);
}
Irrational answered 9/7, 2010 at 13:0 Comment(0)
S
0
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
    fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
Shaff answered 14/1, 2014 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.