Как получить MemoryStream из потока в .NET?
У меня есть следующий метод конструктора, который открывает MemoryStream
из пути к файлу:
MemoryStream _ms;
public MyClass(string filePath)
{
byte[] docBytes = File.ReadAllBytes(filePath);
_ms = new MemoryStream();
_ms.Write(docBytes, 0, docBytes.Length);
}
Мне нужно изменить это, чтобы принять Stream
вместо пути к файлу. Самый простой/самый эффективный способ получить MemoryStream
из объекта Stream
?
Ответы
Ответ 1
Если вы изменяете свой класс, чтобы принять Stream вместо имени файла, не беспокойтесь о преобразовании в MemoryStream. Пусть основной поток обрабатывает операции:
public class MyClass
{
Stream _s;
public MyClass(Stream s) { _s = s; }
}
Но если вам действительно нужен MemoryStream для внутренних операций, вам придется скопировать данные из исходного потока в MemoryStream:
public MyClass(Stream stream)
{
_ms = new MemoryStream();
CopyStream(stream, _ms);
}
// Merged From linked CopyStream below and Jon Skeet 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);
}
}
Ответ 2
В .NET 4 вы можете использовать Stream.CopyTo для копирования потока вместо методов home- brew, перечисленных в другие ответы.
MemoryStream _ms;
public MyClass(Stream sourceStream)
_ms = new MemoryStream();
sourceStream.CopyTo(_ms);
}
Ответ 3
Используйте это:
var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
Это преобразует Stream
в MemoryStream
.
Ответ 4
Вам нужно будет прочитать все данные объекта Stream в буфере byte[]
, а затем передать его в MemoryStream
через свой конструктор. Может быть, лучше быть более конкретным относительно типа объекта потока, который вы используете. Stream
является очень общим и не может реализовать атрибут Length
, что весьма полезно при чтении данных.
Вот вам какой-то код:
public MyClass(Stream inputStream) {
byte[] inputBuffer = new byte[inputStream.Length];
inputStream.Read(inputBuffer, 0, inputBuffer.Length);
_ms = new MemoryStream(inputBuffer);
}
Если объект Stream
не реализует атрибут Length
, вам придется реализовать что-то вроде этого:
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;
}
Ответ 5
Как скопировать содержимое одного потока в другой?
см. это. принять поток и скопировать в память. вы не должны использовать .Length
только для Stream
, потому что это не обязательно реализуется в каждом конкретном потоке.
Ответ 6
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);
}
Ответ 7
Я использую эту комбинацию методов расширения:
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);
}
}
Ответ 8
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}