Почему мой GZipStream не доступен для записи?

В моей программе есть ресурсы, сжатые GZ, и мне нужно иметь возможность записывать их во временные файлы для использования. Я написал следующую функцию для записи файлов и возврата true в случае успеха или false в случае неудачи. Кроме того, я поместил туда try/catch, который показывает MessageBox в случае ошибки:

private static bool extractCompressedResource(byte[] resource, string path)
{
  try
  {
    using (MemoryStream ms = new MemoryStream(resource))
    {
      using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
      {
        using (GZipStream zs = new GZipStream(fs, CompressionMode.Decompress))
        {
          ms.CopyTo(zs); // Throws exception

          zs.Close();
          ms.Close();
        }
      }
    }
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message); // Stream is not writeable
    return false;
  }

  return true;
}

Я добавил комментарий к строке, которая вызывает исключение. Если я поставлю точку останова на эту строку и загляну внутрь GZipStream, то увижу, что она недоступна для записи (что и вызывает проблему).

Я что-то не так делаю, или это ограничение класса GZipStream?


person Ozzah    schedule 17.11.2011    source источник
comment
Нет необходимости закрывать потоки в используемом блоке, они будут автоматически закрыты при удалении.   -  person musefan    schedule 17.11.2011
comment
Кроме того, как написано, GZipStream удаляет FileStream при удалении GZipStream. Также к OP: эмпирически мы видели проблемы, когда вы явно не вызываете .Flush как для «zs», так и для «fs» в вашем примере перед удалением.   -  person Joe    schedule 17.11.2011


Ответы (1)


Вы неправильно разводите трубы. Исправить:

using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
using (MemoryStream ms = new MemoryStream(resource))
using (GZipStream zs = new GZipStream(ms, CompressionMode.Decompress))
{
   zs.CopyTo(fs);
}
person Hans Passant    schedule 17.11.2011
comment
Ваши решения работают. Я вижу, что происходит: вы распаковываете по мере чтения MemoryStream и записываете распакованные данные прямо в файл. Я пытался прочитать сжатые данные из MemoryStream и распаковать при записи в файл. TBH Я не понимаю, почему один будет работать, а другой нет - логически они должны иметь одинаковый результат. Спасибо, Ганс! - person Ozzah; 17.11.2011