2013-04-25 2 views
4

Я пишу приложение WPF для рабочего стола (.Net Framework 4.5), и одна из задач - сохранение нескольких файлов в zip-архиве. Я сделал 2 метода. Сначала для создания zip, второй для чтения из него.Как правильно создать ZipArchive?

public static String GetFileContent(String zipPath, String entityName) 
    { 
     String retVal = String.Empty; 

     using (ZipArchive zipfile = ZipFile.OpenRead(zipPath)) 
     {      
      foreach (ZipArchiveEntry entry in zipfile.Entries) 
      { 
       if (entry.Name.ToLower() == entityName) 
       { 
        using (StreamReader s = new StreamReader(entry.Open())) 
        { 
         retVal = s.ReadToEnd(); 
         break; 
        } 
       } 
      } 
     } 

     return retVal; 
    } 

    public static void SetArchive(String path, String zipName, Dictionary<String, String> files) 
    { 
     using (var fileStream = new FileStream(Path.Combine(path, zipName), FileMode.OpenOrCreate)) 
     { 
      using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Create)) 
      {      
       foreach (KeyValuePair<String, String> file in files) 
       { 
        var entry = zip.CreateEntry(file.Key, CompressionLevel.Optimal); 
        using (Stream s = entry.Open()) 
        {   
         byte[] data = Encoding.UTF8.GetBytes(file.Value); 
         s.Write(data, 0, data.Length); 
        } 
       }      
      }    
     } 
    } 

Дело в том, что почтовый архив, созданный и далеко менеджер и WinRAR может открыть его, но когда я использую второй метод, чтобы читать его содержание я получаю

Количество записей ожидаемых в Конца центрального каталога не соответствует количеству записей в Центральном каталоге. в System.IO.Compression.ZipArchive.ReadCentralDirectory() в System.IO.Compression.ZipArchive.get_Entries() в Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent (String zipPath, String entityName) в z: \ Home Inc \ Microsoft.MCS.SPPal \ Microsoft.MCS.SPPal \ Storage \ StorageObject.cs: строка 32 в Microsoft.MCS.SPPal.MainWindow..ctor() в z: \ Home Inc \ Microsoft.MCS.SPPal \ Microsoft.MCS.SPPal \ MainWindow.xaml.cs: линия 48

в рамках эксперимента я создал новый архив в Far Manager и открыл его с помощью метода GetFileContent, и он работает как шарм. Поэтому я думаю, что ошибка должна быть в методе SetArchive.

Любая помощь будет потрясающей, это 3 часа ночи, и я совсем застрял.

P.S: Я знаю, дизайн кода сосать, он был переписан десятки раз.

ответ

-4

Для лучшего сжатия можно использовать 7zip библиотеку. Таким образом:

public void AddToArchive(string fileToBeZipped, string zipDestination) 
{ 
    DirectoryInfo Di = new DirectoryInfo(zipDestination); 
    StringBuilder sb_archiveFile = new StringBuilder(zipDestination + Path.DirectorySeparatorChar + Di.Name + @".7z"); 
    string archiveFile = sb_archiveFile.ToString(); 


    SevenZip.SevenZipCompressor compressor = new SevenZipCompressor(); 

    Console.WriteLine("zip destination : " + Di.Name); 
    if (!File.Exists(fileToBeZipped)) 
    { 
     Console.WriteLine("Appending {0} to Archive ", fileToBeZipped); 
     compressor.CompressionMode = SevenZip.CompressionMode.Append; 
    } 
    else 
    { 
     Console.WriteLine("Creating {0} at Destination {1}....", fileToBeZipped, archiveFile); 
     Console.WriteLine("CREATING:: "); 
     compressor.CompressionMode = SevenZip.CompressionMode.Create; 
    } 
    compressor.CompressionLevel = CompressionLevel.Normal; 
    compressor.CompressionMethod = CompressionMethod.Lzma; 
    compressor.CompressionMode = CompressionMode.Append; 

    compressor.CompressDirectory(zipDestination, archiveFile); 



    compressor.CompressStream(streamer, streamer2); 
} 

и вызова метода с: AddToArchive (inFolder, splitIntoDir);

Вы можете скачать исходный код 7zip here.

Вы можете установить пакет Nuget для 7zip here для Visual Studio.

+0

Вопрос в том, как правильно создать новый ZipArchive. ZipArchive!= SevenZipCompressor. – Bardicer

+0

Это не помогло ответить на вопрос, указанный в названии. – Dave

+0

Это была одна из моих первых сообщений, единственная моя цель - помочь с другим решением, но извините, если мое решение никому не нравится. – Joseph

3

Мне удалось заставить это работать, добавив явный вызов Dispose() в ZipArchive до того, как он вышел из области действия в методе SetArchive().

zip.Dispose(); 
+1

Вы имеете в виду 'using (ZipArchive zip = new ZipArchive (...))' не выполнял свою работу? Блоки 'using' специально предназначены для использования с одноразовыми объектами ... –

+0

Хорошая точка. Я не использовал «использование». Также отлично работает переход на «использование». –

+0

В коде OP есть «используемые» блоки для всех расходных материалов, не стесняйтесь редактировать сообщение и добавлять полный рабочий код :) –

0

При попытке открыть почтовые файлы, содержащие файлы, которые были больше, чем 4 ГБ перед сжатием, которые были сжаты с использованием Deflate64 (созданные с помощью оболочки Windows, или 7-Zip) я получил

Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory 

при распаковке с System.IO.Compression.ZipFile на Windows 2012 R2. Эти файлы казались законными застежками, потому что Windows Shell, 7-zip и Info-zip могли их распаковать. Единственными крупными файловыми архивами zip, распакованными без ошибок с System.IO.Compression.ZipFile, были те, которые были созданы с помощью Zip64 Info-zip.

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