1

I've been knocking my head on this for 2 days. We're using 7ZipSharp to create .7z files from several source files (incoming emails in fact).

In order to optimize the application, I want to avoid hard disk access so I switched to the CompressStreams function family.

The code using filenames instead of Streams works perfectly. When switching to Streams, I get the "KeyNotFoundException", only when CompressionMode = Append.

My test code:

for (var i = 0; i < numFiles; i++)
        {                
            //if(i > 0)
            //    compressor.CompressionMode = CompressionMode.Append;            
            Console.WriteLine("Adding copy num " + (i + 1) + " to the archive");
            SevenZipUtil.AddStream(File.OpenRead(sampleFile), "email-" + i + ".eml", outFile);

        }

Helper method code:

public static void AddStream(Stream inStream, string fileName, string destinationFile)
    {
        SevenZipCompressor comp = new SevenZipCompressor();
        comp.ArchiveFormat = OutArchiveFormat.SevenZip;
        comp.CompressionLevel = CompressionLevel.Ultra;
        if(File.Exists(destinationFile))
        {

            comp.CompressionMode = CompressionMode.Append;
        }

        FileStream outStream = File.OpenWrite(destinationFile);
        comp.DefaultItemName = fileName;
        comp.CompressStream(inStream, outStream);
        outStream.Flush();
        outStream.Close();            
    }

Error source is file LibraryManager.cs, method InArchive, line 428.

if (_inArchives[user][format] == null

To summarize:

  1. Appending with files instead of Streams, OK
  2. CompressStream in mode = Create, OK
  3. Afterwards, CompressStream in mode = Append fails.

Has anyone any working code of adding several streams to a .7z file, or may this be a bug I should post to the SevenZipSharp forum?

Thanks,

CharlieBrown
  • 4,143
  • 23
  • 24

2 Answers2

4

Would CompressStreamDictionary work for you?

void TestZipping()
{
    SevenZipCompressor compressor = new SevenZipCompressor
    {
        ArchiveFormat = OutArchiveFormat.SevenZip,
        CompressionLevel = CompressionLevel.Ultra,
    };

    using (Stream output = File.Open("test.7z", FileMode.CreateNew))
    using (Stream file1 = File.Open("test1.txt", FileMode.Open))
    using (Stream file2 = File.Open("test2.txt", FileMode.Open))
    {
        compressor.CompressStreamDictionary(new Dictionary<string, Stream> {{ "test1.txt", file1 }, { "test2.txt", file2 }}, output);
    }
}

I suspect that the way you are trying to do it is creating several complete archives consecutively in one stream, rather than appending files into a single archive. Though it might also be due to a lack of resource management (you should be wrapping the lifetime of those streams in using blocks, or otherwise disposing of them properly).

Marc
  • 408
  • 3
  • 6
  • Marc, thanks for you answer. The 7zip code is used inside a process that's consuming from a queue of incoming emails. I ended up using SharpZipLib. We'll loose a bit of compression rate, but worked perfect wihin 10 min after downloading the library. – CharlieBrown Jul 04 '11 at 06:52
  • I like the stream to stream implementation here. Very nice. – Gregory A Beamer Jul 07 '11 at 19:13
0

A stream is a method of getting items from one location to another; it is a behavior type of object that moves from state to state. This means it is not an endpoint or state type of object. You can't add to behavior, you add to state. So, this is not a bug.

That is probably not helpful. See if there is some type of "memory" file location (i.e. the entire file in memory) and then use that as a starting point to add to. I am not sure it is there, as compressed files can get huge.

Gregory A Beamer
  • 16,870
  • 3
  • 25
  • 32
  • thanks for the unwanted and criptic, yet insightful, overview of what a Stream is. In my particular context, it's just a C# object with properties. In an even more particular context, it's exactly an in-memory byte array. Given that this particular library which is a tag in this question has a function that receives a Stream as argument, I would have appreciated a little more down-to-earth answer to my question. Thanks anyway, I'll wait for someone who has actually used the library. – CharlieBrown Jun 30 '11 at 16:41