Ошибка извлечения zip-файла в памяти с помощью C# DotNetZip

Я пытаюсь загрузить и распаковать zip-файл на С#, в частности DotNetZip.

Когда я запускаю этот код...

        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(reportUrl);
        HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
        Stream stream = response.GetResponseStream();
        MemoryStream ms = new MemoryStream();

        stream.CopyTo(ms);
        ms.Seek(0, 0);
        ZipInputStream zip = new ZipInputStream(ms);
        zip.Seek(0, 0);

        ZipEntry e = zip.GetNextEntry();
        string s = e.FileName;

        MemoryStream ms2 = new MemoryStream();
        e.Extract(ms2);

После выполнения метода Extract я получаю...

        $exception  {"Object reference not set to an instance of an object."}   System.Exception {System.NullReferenceException}

Есть предположения? Спасибо!

Вот как выглядит объект до запуска метода


person Charles Offenbacher    schedule 16.06.2011    source источник
comment
Моя непосредственная мысль заключается в том, что InputStream имеет значение null   -  person Ell    schedule 16.06.2011
comment
вы пытались использовать другой экземпляр потока памяти?   -  person Mike Miller    schedule 16.06.2011
comment
Что вы имеете в виду после выполнения метода Extract? Выполняется ли он правильно, прежде чем генерировать исключение? Какая следующая строка кода после Extract?   -  person Ethan Cabiac    schedule 16.06.2011
comment
Хорошо, мне было интересно, что InputStream тоже имеет значение null, но я не могу понять ничего плохого в моей конструкции ZipInputStream, которая могла бы вызвать это. И я не уверен, что это должно быть чем-то, потому что у меня сложилось впечатление, что ZipEntry уже скопировала свои данные из потока, который ее создал.   -  person Charles Offenbacher    schedule 16.06.2011
comment
@ Итан, это конец функции. Извините за неясность, метод Extract вызывает исключение.   -  person Charles Offenbacher    schedule 16.06.2011
comment
@ Майк, хммм ... что ты имеешь в виду под использованием другого экземпляра потока памяти? Я новичок в C#, но я инициализирую его, копирую в него и тут же использую.   -  person Charles Offenbacher    schedule 16.06.2011
comment
Вы пытаетесь извлечь из или в поток памяти?   -  person Ethan Cabiac    schedule 16.06.2011
comment
Я думаю, что в зависимости от того, как вы используете библиотеку, вы читаете/записываете в один и тот же поток. Попробуйте MemoryStream ms2 = new MemoryStream();e.Extract(ms2);   -  person Mike Miller    schedule 16.06.2011
comment
О, спасибо, Майк. Хороший улов. Я считаю, что я определенно делал это раньше и у меня были проблемы, но я обязательно попробую еще раз. Упс.   -  person Charles Offenbacher    schedule 16.06.2011
comment
Я опубликую как ответ, пожалуйста, делайте с ним, как считаете нужным после тестирования: D   -  person Mike Miller    schedule 16.06.2011
comment
Да, такое же исключение. :( Я обновлю свой вопрос, чтобы отразить изменения.   -  person Charles Offenbacher    schedule 16.06.2011


Ответы (1)


Трудно сказать, почему ваш код не работает. Я бы начал с упрощения и убедился, что я правильно распоряжаюсь всеми одноразовыми ресурсами, такими как потоки:

class Program
{
    static void Main()
    {
        var url = "http://downloads.sourceforge.net/project/junit/junit/3.8.1/junit3.8.1.zip";
        using (var client = new WebClient())
        using (var zip = ZipFile.Read(client.DownloadData(url)))
        {
            foreach (var entry in zip)
            {
                entry.Extract(".");
            }        
        }
    }
}

Обязательно ознакомьтесь с документацией, в которой содержится множество полезных примеров использования библиотеки DotNetZip.

person Darin Dimitrov    schedule 16.06.2011
comment
Привет, спасибо за ответ Дарин! Однако у меня это не компилируется (.NET 4.0, последняя версия DotNetZip). Я не хочу разбивать ваш ответ, полагаясь на мой несуществующий С#, чтобы заставить его работать... как лучше всего перейти от Byte.Array (возвращаемое значение DownloadData) к IO.Stream, который требуется для команда Читать?? - person Charles Offenbacher; 16.06.2011
comment
@ Чарльз Оффенбахер, какую ошибку вы получаете? Потому что я только что протестировал этот код на своей Win7 x64 VS2010 .NET 4.0, и он отлично работал. - person Darin Dimitrov; 16.06.2011
comment
ZipFile.Read, кажется, принимает только строку имени файла или поток для меня ... странно, я тоже на VS2010 .NET 4.0 Win7 x64 .... хммм ... 1 сек. - person Charles Offenbacher; 16.06.2011
comment
@Charles Offenbacher, есть много перегрузок ZipFile.Read. Для удобства в моем примере я использую тот, который принимает массив байтов, потому что именно его возвращает метод client.DownloadData. - person Darin Dimitrov; 16.06.2011
comment
Ошибка 3. Аргумент 1: невозможно преобразовать byte[] в System.IO.Stream. - person Charles Offenbacher; 16.06.2011
comment
@Charles Offenbacher, вы загрузили последнюю версию DotNetZip? Я использовал NuGet, чтобы получить его. У меня есть 19 перегрузок статического метода ZipFile.Read :-) - person Darin Dimitrov; 16.06.2011
comment
Ха-ха :) Я считаю, что есть много перегрузок, просто они у меня не работают. Позвольте мне попробовать вернуться к другой версии DotNetZip... Я на Альфе... хотя я был бы удивлен, если бы они изменили это. - person Charles Offenbacher; 16.06.2011
comment
@Charles Offenbacher, вот что я сделал: создал новое консольное приложение в VS2010, установил пакет NuGet DotNetZip (оказывается, версия 1.9), поместил код, который я показал в Program.cs, и рок-н-ролл. - person Darin Dimitrov; 16.06.2011
comment
Вау! Красивый! NuGet решил эту проблему. Я думаю, что это понизило меня, но теперь ваш код компилируется. Спасибо - person Charles Offenbacher; 16.06.2011
comment
Почти уверен, что сейчас все работает. До сих пор понятия не имею о ZipInputStream, но у меня сложилось впечатление, что ZipFile намного старше и надежнее, так что это отличное решение. Большое спасибо!! - person Charles Offenbacher; 16.06.2011
comment
Я вижу ту же ошибку, что и Чарльз, и я только что установил DotNetZip через nuget. По какой-то причине я вижу только 4 перегрузки, и все они хотят поток в качестве ввода. - person Ben Mills; 09.01.2013