2009-06-10 3 views
8

Я играл с тем, что, как я думал, было простой идеей. Я хочу, чтобы иметь возможность читать в файле откуда-то (сайт, файловая система, ftp), выполнять некоторые операции над ним (сжимать, шифровать и т. Д.), А затем сохранять его где-нибудь (где-то может быть файловая система, ftp или что-то еще) , Это базовый дизайн трубопровода. То, что я хотел бы сделать, это прочитать в файле и поместить его на MemoryStream, затем выполнить операции с данными в MemoryStream, а затем сохранить эти данные в MemoryStream где-нибудь. Я думал, что я мог бы использовать один и тот же поток, чтобы сделать это, но работать в нескольких задач:Поток Повторное использование в C#

  1. Everytime я использую StreamWriter или StreamReader, мне нужно, чтобы закрыть его и что закрывает поток, так что я не могу использовать его больше , Кажется, должен быть какой-то способ обойти это.
  2. Некоторые из этих файлов могут быть большими, и поэтому я могу потерять память, если попытаюсь сразу прочитать все это.

Я надеялся, что вы сможете развернуть каждый из шагов в виде отдельных потоков и начать этап сжатия, как только будут данные в потоке, а затем, как только сжатие будет иметь сжатые данные в потоке я мог бы начать его сохранять (например). Легко ли это возможно с потоками C#? У кого-нибудь есть мысли о том, как добиться этого лучше всего?

Спасибо,

Майк

ответ

4

Используя вспомогательный метод для управления потоковой передачи:

static public void StreamCopy(Stream source, Stream target) 
{ 
    byte[] buffer = new byte[8 * 1024]; 

    int size; 
    do 
    { 
     size = source.Read(buffer, 0, 8 * 1024); 
     target.Write(buffer, 0, size); 
    } while (size > 0); 
} 

Вы можете легко объединить все, что вам нужно:

using (FileStream iFile = new FileStream(...)) 
using (FileStream oFile = new FileStream(...)) 
using (DeflateStream oZip = new DeflateStream(outFile, CompressionMode.Compress)) 
    StreamCopy(iFile, oZip); 

В зависимости от того, что на самом деле пытаются это сделать, вы по-разному связываете потоки. Это также использует относительно небольшую память, поскольку в памяти хранятся только данные.

+0

С .NET 4.0 вы можете использовать встроенные '.CopyTo' и'.CopyToAsync', чтобы скопировать поток в другой –

1

StreamReader/StreamWriter не должен был разработан, чтобы закрыть свой основной поток - это ужасная неточность в BCL. Но они делают, они не будут изменены (из-за обратной совместимости), поэтому мы застряли в этой катастрофе API.

Но есть некоторые устоявшиеся обходные пути, если вы хотите использовать StreamReader/Writer, но продолжайте открывать Stream после этого.

  • Для StreamReader: не утилизируйте StreamReader. Это так просто. Безвредно просто позволить StreamReader идти без вызова Dispose. Единственный эффект заключается в том, что ваш поток не будет преждевременно закрыт, что на самом деле плюс.
  • Для StreamWriter: могут быть буферизованные данные, поэтому вы не можете уйти, просто отпустив его. Вы должны вызвать Flush, чтобы убедиться, что буферизованные данные будут записаны в Stream. Затем вы можете просто запустить StreamWriter. (. В основном, вы поставите Flush, где вы обычно бы поставить Dispose)
+2

Если вам действительно нужно использовать StreamReader и StreamWriter, но ДОЛЖНЫ убедиться, что базовый поток никогда не закрыт, создайте класс Proxy Stream, который просто передает каждый вызов базовому потоку, за исключением вызовов в Close и Утилизируйте методы (которые вы проигнорируете) и оберните свой базовый поток прокси-сервером при передаче его конструкторам Reader/Writer. Затем вы можете использовать классы Reader/Writer. –

Смежные вопросы