icsharpcode / SharpZipLib

#ziplib is a Zip, GZip, Tar and BZip2 library written entirely in C# for the .NET platform.
http://icsharpcode.github.io/SharpZipLib/
MIT License
3.71k stars 977 forks source link

Can't open empty file #879

Open MagnusBeijer opened 2 weeks ago

MagnusBeijer commented 2 weeks ago

Describe the bug

If a zip file is created without adding any files to it, it can not be opened and throws: ICSharpCode.SharpZipLib.Zip.ZipException: Cannot find central directory

Steps to reproduce

    using (var b = ZipFile.Create("c:\\temp\\sharpzip.zip")) { }
    using (var b = new ZipFile("c:\\temp\\sharpzip.zip")) { } // Throws exception

Expected behaviour

The file should be opened and contain no files.

Operating System

Windows

Framework Version

.NET 7

Tags

ZIP

Additional context

No response

jagmehta commented 5 days ago
    public ZipFile(string name, StringCodec stringCodec)
    {
        name_ = name ?? throw new ArgumentNullException(nameof(name));

        baseStream_ = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read);
        isStreamOwner = true;

        if (stringCodec != null)
        {
            _stringCodec = stringCodec;
        }

        if (baseStream_.Length > 0)
        {
            try
            {
                ReadEntries();
            }
            catch
            {
                DisposeInternal(true);
                throw;
            }
        }
        else
        {
            entries_ = Empty.Array<ZipEntry>();
            isNewArchive_ = true;
        }
    }

    public ZipFile(FileStream file, bool leaveOpen)
    {
        if (file == null)
        {
            throw new ArgumentNullException(nameof(file));
        }

        if (!file.CanSeek)
        {
            throw new ArgumentException("Stream is not seekable", nameof(file));
        }

        baseStream_ = file;
        name_ = file.Name;
        isStreamOwner = !leaveOpen;

        if (baseStream_.Length > 0)
        {
            try
            {
                ReadEntries();
            }
            catch
            {
                DisposeInternal(true);
                throw;
            }
        }
        else
        {
            entries_ = Empty.Array<ZipEntry>();
            isNewArchive_ = true;
        }
    }

This is the fix.

MagnusBeijer commented 4 days ago

Doing this ensures that the central directory gets created:

using (var zipFile = ZipFile.Create("c:\\temp\\sharpzip.zip"))
{
    zipFile.BeginUpdate();
    zipFile.CommitUpdate();
 }