-4

How do you write a ZipFile to disk using SharpZipLib?

  • Do you have to open an output stream to write a ZipFile to disk?
  • Is there some way to just get the ZipFile bytes and do File.WriteAllBytes()?

Note: My question is not about compression. Just about taking an existing ZipFile and writing it to disk.

Also, please note, I have already perused docs and this use case is not there.

https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
ina
  • 19,167
  • 39
  • 122
  • 201
  • https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples – Retired Ninja Nov 02 '20 at 22:40
  • @RetiredNinja so I've been through those examples before posting. They don't have an example that saves a zip - that starts with a complete `ZipFile`. I am not talking about compressing files - simply saving a `ZipFile` to disk. – ina Nov 02 '20 at 22:47
  • Taking an existing zip file and writing it to disk ? isn't it already on disk ? If not where is it ? Is it in bytes ? – TheGeneral Nov 02 '20 at 22:52
  • 3
    @ina this question will be closed if you don't put a little more detail into the question. At the moment it is unclear what you are asking. Though, I am sure this could be answered in seconds if you could just clear up the fundamental point... Where are you getting this zip file from. If its from byes, just write it to disk using a `File` method, if its from stream, just write it to disk using a `FileStream`. if it is already on disk, just use `File.Copy` – TheGeneral Nov 02 '20 at 23:15
  • @TheGeneral NO, it is not on disk. it's available as a SharpZipLib `ZipFile` – ina Nov 03 '20 at 01:20

1 Answers1

2

Do you have to open an output stream to write a ZipFile to disk?

According to their Github samples, they are suggesting to create a stream object using ZipOutputStream to write the file and to write into the file being zipped, you need to open a FileStream to write the objects into the library.

Here is the sample of the code that you can use to zip files.

// Depending on the directory this could be very large and would require more attention
// in a commercial package.
string[] filenames = Directory.GetFiles("directory");

// 'using' statements guarantee the stream is closed properly which is a big source
// of problems otherwise.  Its exception safe as well which is great.
using (ZipOutputStream s = new ZipOutputStream(File.Create("outputfile")))
{

    s.SetLevel(9); // 0 - store only to 9 - means best compression

    byte[] buffer = new byte[4096];

    foreach (string file in filenames)
    {

        // Using GetFileName makes the result compatible with XP
        // as the resulting path is not absolute.
        var entry = new ZipEntry(Path.GetFileName(file));

        // Setup the entry data as required.

        // Crc and size are handled by the library for seakable streams
        // so no need to do them here.

        // Could also use the last write time or similar for the file.
        entry.DateTime = DateTime.Now;
        s.PutNextEntry(entry);

        using (FileStream fs = File.OpenRead(file)) 
        {

            // Using a fixed size buffer here makes no noticeable difference for output
            // but keeps a lid on memory usage.
            int sourceBytes;
            do
            {
            sourceBytes = fs.Read(buffer, 0, buffer.Length);
            s.Write(buffer, 0, sourceBytes);
            } while (sourceBytes > 0);
        }
    }

    // Finish/Close arent needed strictly as the using statement does this automatically

    // Finish is important to ensure trailing information for a Zip file is appended.  Without this
    // the created file would be invalid.
    s.Finish();

    // Close is important to wrap things up and unlock the file.
    s.Close();
}

Is there some way to just get the ZipFile bytes and do File.WriteAllBytes()?

If you are asking if we can write bytes of the files directly without opening the FileStream to read the files that are to be written in the zip file, then, Yes, you can write all bytes at once into the source zip file but that is a bad way as it will read all the bytes at once into the memory and this could be disastrous if the files being zipped are huge in size. Anyways, here is how you can do it:

Just replace the FileStream part in the above sample with this code:

var bytes = File.ReadAllBytes(file);
s.Write(bytes, 0, bytes.Length); // write all bytes from 0 to the length of the bytes

So, the updated source code would be:

string[] filenames = Directory.GetFiles("directory");

using (ZipOutputStream s = new ZipOutputStream(File.Create("outputfile")))
{

    s.SetLevel(9);

    byte[] buffer = new byte[4096];

    foreach (string file in filenames)
    {
        var entry = new ZipEntry(Path.GetFileName(file));

        entry.DateTime = DateTime.Now;
        s.PutNextEntry(entry);
        var bytes = File.ReadAllBytes(file);
        s.Write(bytes, 0, bytes.Length);
    }
    s.Finish();
    s.Close();
}
Jamshaid K.
  • 3,555
  • 1
  • 27
  • 42
  • This doesn't work for me exactly as none of these cases apply. I am trying to write to disk a `ZipFile` that is passed from a closed source SDK. – ina Nov 03 '20 at 08:02
  • And for that you will have to tell us how that zip file is being passed, either as a stream or bytes or something else? – Jamshaid K. Nov 03 '20 at 13:07
  • `ZipFile` is an object type in SharpZipLib. You can iterate through its `ZipEntry` in the zip file, where `zipFile.GetInputStream(zipEntry)` gets you a stream of each file... It's being passed as a `ZipFile` object. However, i cannot seem to access the bytes through that method https://stackoverflow.com/questions/64668726/unity-sharpziplib-zip-zipentry-cannot-access-a-closed-stream-for-loading-bytes – ina Nov 03 '20 at 20:37