2017-01-26 15 views
0

Учитывая zip-файл, мне нужно его заново создать с указанным уровнем сжатия (например, без сжатия).Повторно создать zip-файл из другого zip-файла

Я почти там, но получаю сообщение об ошибке:

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

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

public static byte[] ReCompress(byte[] originalArchive, CompressionLevel newCompressionLevel) 
{ 
    var entries = new Dictionary<string, byte[]>(); 

    /////////////////////////// 
    // STEP 1: EXTRACT ALL FILES 
    /////////////////////////// 
    using (var ms = new MemoryStream(originalArchive)) 
    using (var originalZip = new ZipArchive(ms, ZipArchiveMode.Read)) 
    { 
     foreach (var entry in originalZip.Entries) 
     { 
      var isFolder = entry.FullName.EndsWith("/"); 
      if (!isFolder) 
      { 
       using (var stream = entry.Open()) 
       using (var entryMS = new MemoryStream()) 
       { 
        stream.CopyTo(entryMS); 
        entries.Add(entry.FullName, entryMS.ToArray()); 
       } 

      } 
      else 
      { 
       entries.Add(entry.FullName, new byte[0]); 
      } 
     } 
    } 

    /////////////////////////// 
    // STEP 2: BUILD ZIP FILE 
    /////////////////////////// 
    using (var ms = new MemoryStream()) 
    using (var newArchive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     foreach (var uncompressedEntry in entries) 
     { 
      var newEntry = newArchive.CreateEntry(uncompressedEntry.Key, newCompressionLevel); 
      using (var entryStream = newEntry.Open()) 
      using (var writer = new BinaryWriter(entryStream, Encoding.UTF8)) 
      { 
       writer.Write(uncompressedEntry.Value); 
      } 
     } 
     return ms.ToArray(); 
    } 
} 

В конце функции, если я делаю:

File.WriteAllBytes(@"D:\test.zip", ms.ToArray()); 

Это создает правильно структуру архива размером 90mb, но файлы не являются извлекаемыми.

Если я заканчиваю return ms.ToArray(), он возвращает массив байтов ~130kb.

+0

Ну длинный путь вокруг будет извлечь первый архив в папку темп и повторно сжать его в новый архив. – Nkosi

ответ

1

Почтовый архив поврежден, потому что вы прочитали его содержимое от MemoryStream до его завершения. Чтобы завершить создание архива, необходимо позвонить newArchive.Dispose() перед вызовом ms.ToArray(). В данном конкретном случае, вы можете сделать это следующим образом:

using (var ms = new MemoryStream()) 
{ 
    using (var newArchive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     foreach (var uncompressedEntry in entries) 
     { 
      var newEntry = newArchive.CreateEntry(uncompressedEntry.Key, newCompressionLevel); 
      using (var entryStream = newEntry.Open()) 
      using (var writer = new BinaryWriter(entryStream, Encoding.UTF8)) 
      { 
       writer.Write(uncompressedEntry.Value); 
      } 
     } 
    } 

    return ms.ToArray(); 
} 
+0

Работал шармом спасибо! –

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

  • Нет связанных вопросов^_^