2013-12-06 4 views
5

Я пытаюсь прочитать в файл и сжать его с помощью GZipStream, как это:сжатия GZipStream не работает

using (var outStream = new MemoryStream()) 
{ 
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) 
    { 
     using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress)) 
     { 
      fileStream.CopyTo(gzipStream); 

      Debug.WriteLine(
       "Compressed from {0} to {1} bytes", 
       fileStream.Length, 
       outStream.Length); 

      // "outStream" is utilised here (persisted to a NoSql database). 
     } 
    } 
} 

Проблема заключается в том, что outStream.Length всегда показывает 10 байт. Что я делаю не так?

Я пыталась дозвониться gzipStream.Close() после fileStream.CopyTo линии (как это было предложено в других форумах), но это, кажется, близко outStream тоже, так что последующий код, который использует его падает.

+0

Согласно [msdn] [1], нет причин слишком доверять Stream.length proprety, который может быть или не быть реализован. Проверяли ли вы другим способом, что полученный выход неверен? [1]: http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.length%28v=vs.110%29.aspx – C4stor

ответ

5

MSDN говорит: The write operation might not occur immediately but is buffered until the buffer size is reached or until the Flush or Close method is called.

Другими словами, тот факт, что все операции записи выполняются не означает, что данные уже в MemoryStream. Вы должны сделать gzipStream.Flush() или закрыть gzipStream.

Пример:

using (var outStream = new MemoryStream()) 
{ 
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) 
    { 
     using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress)) 
     { 
      fileStream.CopyTo(gzipStream); 
     } 

     Debug.WriteLine(
       "Compressed from {0} to {1} bytes", 
       fileStream.Length, 
       outStream.Length); 

     // "outStream" is utilised here (persisted to a NoSql database). 
    } 
} 

Кроме того, в идеале, поставить его вне FileStream, а также - вы хотите, чтобы закрыть файлы, как только вы можете, не дожидаясь какой-либо другой обработки, чтобы закончить.

+2

Я подозревал, что отсутствует промывка быть виновником сначала, но [docs на 'GZipStream.Flush'] (http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.flush%28v=vs.110% 29.aspx) явно указывают, что «текущая реализация этого метода не имеет функциональности», закрытие потока действительно является единственным вариантом. –

+2

@ O.R.Mapper: ILSpy, похоже, подтверждает это. Вау, это немного под поясом. Я предполагаю, что у них не было возможности реализовать его, так как он не может работать постепенно, вам, вероятно, нужно будет все сжатые и записанные данные сразу. – Luaan

+1

Это не сработало - обертывание использования вокруг 'fileStream.CopyTo()' (или, действительно, закрытие gzipStream после CopyTo, как упоминалось в моем вопросе) приводит к закрытию 'outStream', что делает его непригодным для использования в более поздних строках. –

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