Как мне "раскошелиться" на поток в.NET?

Как обсуждалось ранее, когда BinaryReader или BinaryWriter закрываются, базовый поток также закрывается (аааа). Рассмотрим эту ситуацию: рутина R передается MemoryStream, скажем M; Я хотел бы написать кое-что M а затем передать его другой процедуре для дополнительной обработки (не обязательно записи). Для удобства хотелось бы завернуть M в BinaryWriter, чтобы сделать мое письмо. После написания я сделал с BinaryWriter, но не с M,

void R(MemoryStream M)
{
    using (B = new BinaryWriter(M))
    {
        // write some stuff using B
    }

    S(M);  // now pass M to another routine for further processing
}

Но я не могу избавиться от BinaryStream без закрытия M,

В: Есть ли способ сделать что-либо из следующего?

  • извлечь базовый байт [] из MemoryStream,
  • клонировать поток
  • вновь открыть поток после его закрытия

7 ответов

Решение

Благодаря нескольким, кто предложил ToArray, меня привели к правильному ответу, а именно: M.GetBuffer. ToArray не так уж плохо, но это

  • делает копию
  • получает только часть буфера

GetBuffer просто получает ссылку на нижележащий байт [], что я и ищу.

Вам лучше получить базовый буфер byte[], используя

byte[] buffer = ms.GetBuffer();

А затем скопируйте байтовые данные, используя метод Array.Copy(). Вы можете создать новый поток с ним.

Вы можете использовать такие вещи, как MiscUtil.IO.NonClosingStreamWrapper в MiscUtil, который оборачивает Stream и просто игнорирует Close/Dispose Запросы. Для этой цели.

void R(MemoryStream M)
{
    using (B = new BinaryWriter(new NonClosingStreamWrapper(M)))
    {
        // write some stuff using B
    }

    S(M);  // now pass M to another routine for further processing
}    

Вы можете:

  • Вызовите M.ToArray(), чтобы получить поток в виде массива байтов.
  • Подкласс BinaryWriter и переопределить метод Dispose, чтобы предотвратить закрытие дочернего потока

Просто добавьте это здесь, очень простым решением было бы не Dispose() писатель.

void R(MemoryStream M)
{
    B = new BinaryWriter(M);

    // write some stuff using B        
    B.Flush();
    S(M);  // now pass M to another routine for further processing
}

Теперь вам остается только позаботиться о том, чтобы оставить B в области видимости, что будет во время R().

Возможно, это не лучшее решение, но стоит отметить, что читатели и писатели не нуждаются в утилизации сами.

Несколько наивный подход заключается в использовании

byte buf[] = MemoryStream.ToArray();

Копировать содержимое потока в байтовый массив. Вы можете превратить его обратно в поток с

MemoryStream ms = new MemoryStream(buf);

В соответствии с этим M.Clone(); должно сработать. Но я могу ошибаться...

Другие вопросы по тегам