Вопрос по c#, .net, stream, memorystream, file-io – Как получить MemoryStream из потока в .NET?

55

У меня есть следующий метод конструктора, который открываетMemoryStream из пути к файлу:

MemoryStream _ms;

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

Мне нужно изменить это, чтобы принятьStream вместо пути к файлу. Какой самый простой / эффективный способ получитьMemoryStream отStream объект?

Если у вас есть Stream, зачем его конвертировать в MemoryStream? Разве вы не можете просто работать с Stream напрямую? Justin Niessner
Также есть случаи, когда низкая производительность при работе с потоками делает MemoryStream более эффективной. Как мой вопрос здесь:stackoverflow.com/questions/50399481/... Chris Rae
Мне нужен MemoryStream из-за других зависимостей. fearofawhackplanet

Ваш Ответ

9   ответов
0

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

Позиция потока равна 0 и готова к использованию.

2

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

Использовать этот:

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

Это преобразуетStream вMemoryStream.

0
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
    fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
3

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

Как скопировать содержимое одного потока в другой?

видеть, что. принять поток и скопировать в память. вы не должны использовать.Length Просто дляStream потому что это не обязательно реализовано в каждом конкретном потоке.

28

чтобы он принимал 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'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);
    }
}
Похоже, одна закрывающая скобка отсутствует. должно бытьwhile((read = input.Read(buffer,0,buffer.Length)) > 0) Stephane Delcroix
Могу добавитьoutput.Position = 0; как самая последняя строка, в противном случае вам нужно будет помнить, чтобы сбросить ее позже. L Co
Я предполагаю, что это> 0 в конце строки? fearofawhackplanet
@fearofawhackplanet - Правильно. Я получил немного удалить счастливым. Исправлена. Justin Niessner
175

В .NET 4 вы можете использоватьStream.CopyTo скопировать поток вместо методов домашнего приготовления, перечисленных в других ответах.

MemoryStream _ms;

public MyClass(Stream sourceStream)

    _ms = new MemoryStream();
    sourceStream.CopyTo(_ms);
}
Убедитесь, что вы сначала установили sourceStream.Position = 0; David Thielen
Вам нужно будет установить _ms.Position = 0; до его использования. ScubaSteve

Похожие вопросы