Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ZIP file created with SharpZipLib cannot be opened on Mac OS X

Tags:

c#

macos

zip

Argh, today is the day of stupid problems and me being an idiot.

I have an application which creates a zip file containing some JPEGs from a certain directory. I use this code in order to:

  • read all files from the directory
  • append each of them to a ZIP file

using (var outStream = new FileStream("Out2.zip", FileMode.Create))
{
    using (var zipStream = new ZipOutputStream(outStream))
    {
        foreach (string pathname in pathnames)
        {
            byte[] buffer = File.ReadAllBytes(pathname);

            ZipEntry entry = new ZipEntry(Path.GetFileName(pathname));
            entry.DateTime = now;

            zipStream.PutNextEntry(entry);
            zipStream.Write(buffer, 0, buffer.Length);
        }
    }
}

All works well under Windows, when I open the file e. g. with WinRAR, the files are extracted. But as soon as I try to unzip my archive on Mac OS X, it only creates a .cpgz file. Pretty useless.

A normal .zip file created manually with the same files on Windows is extracted without any problems on Windows and Mac OS X.

I found the above code on the Internet, so I am not absolutely sure if the whole thing is correct. I wonder if it is needed to use zipStream.Write() in order to write directly to the stream?

like image 880
Max Avatar asked Nov 05 '09 11:11

Max


People also ask

Why are zip files not opening on Mac?

If it won't open with a double-click, it may be corrupted, but you can also try Stuffit Expander and/or The Unarchiver in case it's a non-standard zip. If they can't open it, the problem is with the zip file. Try downloading again.

How do I unzip a zip file on Mac OS X?

Double-click on the zipped file to unzip any zipped file on your Mac. This will prompt the Archive Utility tool to unzip the files in the same folder the zipped file is in. Click appropriate icons to access the extracted files.

How do I open a zip 001 file on a Mac?

What is it?: A free software available from the App Store for Mac OSX computers as well iOS mobile devices. To unzip the your split zipped library with The Unarchiver, you can right-click on the first file “. zip. 001”, hover over “Open With” and select The Unarchiver and it will automatically begin unzipping.

Does macOS support zip files?

Both Mac and Windows come with an inbuilt compression feature that enables you to zip files. The zip files put all your files in one place. The file archive will put all the compressed files in one place. Therefore, it is a suitable option when you want to have a single file.


2 Answers

I don't know for sure, because I am not very familiar with either SharpZipLib or OSX , but I still might have some useful insight for you.

I've spent some time wading through the zip spec, and actually I wrote DotNetZip, which is a zip library for .NET, unrelated to SharpZipLib.

Currently on the user forums for DotNetZip, there's a discussion going on about zip files generated by DotNetZip that cannot be read on OSX. One of the people using the library is having a problem that seems similar to what you are seeing. Except I have no idea what a .cpgxz file is.

We tracked it down, a little. At this point the most promising theory is that OSX does not like "bit 3" in the "general purpose bitfield" in the header of each zip entry.

Bit 3 is not new. PKWare added bit 3 to the spec 17 years ago. It was intended to support streaming generation of archives, in the way that SharpZipLib works. DotNetZip also has a way to produce a zipfile as it is streamed out, and it will also set bit-3 in the zip file if used in this way, although normally DotNetZip will produce a zipfile with bit-3 unset in it.

From what we can tell, when bit 3 is set, the OSX zip reader (whatever it is - like I said I'm not familiar with OSX) chokes on the zip file. The same zip contents produced without bit 3, allows the zip file to be opened. Actually it's not as simple as just flipping one bit - the presence of the bit signals the presence of other metadata. So I am using "bit 3" as a shorthand for all that.

So the theory is that bit 3 causes the problem. I haven't tested this myself. There's been some impedance mismatch on the communication with the person who has the OSX machine - so it is unresolved as yet.

But, if this theory holds, it would explain your situation: that WinRar and any Windows machine can open the file, but OSX cannot.

On the DotNetZip forums, we had a discussion about what to do about the problem. As near as I can tell, the OSX zip reader is broken, and cannot handle bit 3, so the workaround is to produce a zip file with bit 3 unset. I don't know if SharpZipLib can be convinced to do that.

I do know that if you use DotNetZip, and use the normal ZipFile class, and save to a seekable stream (like a filesystem file), you will get a zip that does not have bit 3 set. If the theory is correct, it should open with no problem on the Mac, every time. This is the result the DotNetZip user has reported. It's just one result so not generalizable yet, but it looks plausible.

example code for your scenario:

  using (ZipFile zip = new ZipFile()
  {
      zip.AddFiles(pathnames);
      zip.Save("Out2.zip");
  }

Just for the curious, in DotNetZip you will get bit 3 set if you use the ZipFile class and save it to a nonseekable stream (like ASPNET's Response.OutputStream) or if you use the ZipOutputStream class in DotNetZip, which always writes forward only (no seeking back). I think SharpZipLib's ZipOutputStream is also always "forward only."

like image 64
Cheeso Avatar answered Oct 11 '22 13:10

Cheeso


got the exact same problem today. I tried implementing the CRC stuff as proposed but it didn't help.

I finaly found the solution on this page: http://community.sharpdevelop.net/forums/p/7957/23476.aspx#23476

As a result, I just had to add this line in my code:

oZIPStream.UseZip64 = UseZip64.Off;

And the file opens up as it should on MacOS X :-)

Cheers fred

like image 44
Fred Mauroy Avatar answered Oct 11 '22 14:10

Fred Mauroy