2

I've been playing around with C#'s SharpZip Library (version 0.86.0). I'm basically using it to package a number of files into one clean zip files. Here's what my function looks like to do generate the byte array of the zip file:

public static byte[] CompressToZip(List<Tuple<byte[], string>> fileItemList, int zipLevel = 3)
{
        MemoryStream zipMemoryStream = new MemoryStream();

        ZipOutputStream zOutput = new ZipOutputStream(zipMemoryStream);
        zOutput.SetLevel(zipLevel);

        ICSharpCode.SharpZipLib.Checksums.Crc32 crc = new ICSharpCode.SharpZipLib.Checksums.Crc32();

        foreach (var file in fileItemList)
        {
            ZipEntry entry = new ZipEntry(file.Item2);
            entry.DateTime = DateTime.Now;
            entry.Size = file.Item1.Length;

            crc.Reset();
            crc.Update(file.Item1);

            entry.Crc = crc.Value;

            zOutput.PutNextEntry(entry);
            zOutput.Write(file.Item1, 0, file.Item1.Length);
        }

        zOutput.IsStreamOwner = false;
        zOutput.Finish();
        zOutput.Close();
        zipMemoryStream.Position = 0;

        byte[] zipedFile = zipMemoryStream.ToArray();
        return zipedFile;
    }

The function works fine for files with one item in it. But for some reason when I have two or more I get errors when I go to extract/open it.

PeaZip says:

Archive is not readable

WinZip says:

The compressed size stored in the local header for this file is not the same as the compressed size stored in the central header

but here's the kicker. Windows 8 Archiving tool works just fine with the file. The WinZip error kind of makes me think I'm writing the files to the stream incorrectly. But it looks fine to me. Not sure what to make of this..

EDIT

Here's my changes from codemonkeys input. Looks better to me, but I'm still getting the same errors

public static byte[] CompressToZip(List<Tuple<byte[], string>> fileItemList, int zipLevel = 3)
{
        MemoryStream zipMemoryStream = new MemoryStream();

        ZipOutputStream zOutput = new ZipOutputStream(zipMemoryStream);
        zOutput.SetLevel(zipLevel);

        ICSharpCode.SharpZipLib.Checksums.Crc32 crc = new ICSharpCode.SharpZipLib.Checksums.Crc32();

        foreach (var file in fileItemList)
        {
            ZipEntry entry = new ZipEntry(file.Item2);
            entry.DateTime = DateTime.Now;
            entry.Size = file.Item1.Length;

            crc.Reset();
            crc.Update(file.Item1);

            entry.Crc = crc.Value;

            zOutput.PutNextEntry(entry);
            var memStreamCurrentfile = new MemoryStream(file.Item1);
            StreamUtils.Copy(memStreamCurrentfile, zOutput, new byte[4096]);
            zOutput.CloseEntry();
        }

        zOutput.IsStreamOwner = false;
        zOutput.Finish();
        zOutput.Close();
        zipMemoryStream.Position = 0;

        byte[] zipedFile = zipMemoryStream.ToArray();
        return zipedFile;
    }
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
mBrice1024
  • 790
  • 5
  • 25
  • 1
    The example on https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#anchorMemory adds a `zipStream.CloseEntry();` after every entry. – John Jan 03 '15 at 19:46
  • Just tried it, and used the StreamUtils.Copy() method too. Still the same issue :( – mBrice1024 Jan 03 '15 at 20:16

1 Answers1

3

Figured it out! It seems me setting the Crc and size of file entry was the issue. I assumed it would helped to define those. I guess I was wrong. Here's the final code for all to enjoy:

public static byte[] CompressToZip(List<Tuple<byte[], string>> fileItemList, int zipLevel = 3)
    {
        MemoryStream zipMemoryStream = new MemoryStream();
        ZipOutputStream zOutput = new ZipOutputStream(zipMemoryStream);
        zOutput.SetLevel(zipLevel);
        ICSharpCode.SharpZipLib.Checksums.Crc32 crc = new ICSharpCode.SharpZipLib.Checksums.Crc32();
        foreach (var file in fileItemList)
        {
            ZipEntry entry = new ZipEntry(file.Item2);
            entry.DateTime = DateTime.Now;
            zOutput.PutNextEntry(entry);
            var memStreamCurrentfile = new MemoryStream(file.Item1);
            StreamUtils.Copy(memStreamCurrentfile, zOutput, new byte[4096]);
            zOutput.CloseEntry();
        }
        zOutput.IsStreamOwner = false;
        zOutput.Finish();
        zOutput.Close();
        zipMemoryStream.Position = 0;

        byte[] zipedFile = zipMemoryStream.ToArray();
        return zipedFile;
    }
mBrice1024
  • 790
  • 5
  • 25