Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create ZipArchive correctly?

i'm writing Desktop WPF application (.Net Framework 4.5) and one of tasks is to save multiple files to zip archive. I made 2 methods. First to create zip, second to read from it.

    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);
                    }
                }                    
            }            
        }
    }

Thing is that zip archive created and far manager and WinRAR can open it, but when I use second method to read its content I keep getting

Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. at System.IO.Compression.ZipArchive.ReadCentralDirectory() at System.IO.Compression.ZipArchive.get_Entries() at Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent(String zipPath, String entityName) in z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\Storage\StorageObject.cs:line 32 at Microsoft.MCS.SPPal.MainWindow..ctor() in z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\MainWindow.xaml.cs:line 48

As a part of experiment i created new archive in far manager and opened it up with GetFileContent method, and it works like a charm. So i think error should be in SetArchive method.

Any help would be awesome, it's 3 a.m. and i'm quite stuck.

P.S: I know code design suck, it was rewritten dozens of times.

like image 980
Silverlay Avatar asked Apr 25 '13 22:04

Silverlay


2 Answers

I was able to get this to work by adding an explicit call to Dispose() on the ZipArchive before it went out of scope in the SetArchive() method.

zip.Dispose();
like image 152
Stephen Coy Avatar answered Sep 21 '22 06:09

Stephen Coy


When trying to open zip files containing files that were greater than 4 GB before compression that had been compressed using Deflate64 (created via Windows shell or 7-zip) I got

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

when decompressing with System.IO.Compression.ZipFile on Windows 2012 R2. These files seemed to be legitimate zips because Windows Shell, 7-zip and Info-zip could decompress them. The only large file zip archives that decompressed without error with System.IO.Compression.ZipFile were those created with Info-zip's Zip64.

like image 1
Anon Avatar answered Sep 21 '22 06:09

Anon