如何在.NET 中从记忆流中获取记忆流?

我有以下构造函数方法,它从一个文件路径打开一个 MemoryStream:

MemoryStream _ms;


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

我需要更改它以接受 Stream而不是文件路径。从 Stream对象获得 MemoryStream的最简单/最有效的方法是什么?

146297 次浏览

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.

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

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

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

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);
}
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}

Use this:

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

This will convert Stream to MemoryStream.

You can simply do:

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

Stream position is 0 and ready to use.