Search code examples
c#delegates7ziplzma

How do I create a callback function for the LZMA (7zip) SDK encoder.Code() function?


Below is a small excerpt from a class I'm building for the LZMA (7zip) SDK found here. Everything seems to be working OK for the most part but I'm trying to implement some progress reporting to track the progress of the compression process. On the line below encoder.Code(inStream, outStream, -1, -1, null); I use null when I need to use some form of an ICodeProgress callback.

I just want to create some type of delegate callback to track the progress within the thread I have created in my class.

Class Excerpt:

public class CompressorThreads : CompressorClassEvents
{
    public static class SevenZipCoderProperties
    {
        public static readonly CoderPropID[] PropertyNames =
        {
            CoderPropID.DictionarySize,
            CoderPropID.PosStateBits,
            CoderPropID.LitContextBits,
            CoderPropID.LitPosBits,
            CoderPropID.Algorithm,
            CoderPropID.NumFastBytes,
            CoderPropID.MatchFinder,
            CoderPropID.EndMarker,
        };

        public static readonly object[] PropertyValues =
        {
            (Int32)LzmaDictionarySize.VerySmall,
            (Int32)(2),
            (Int32)(3),
            (Int32)(0),
            (Int32)(2),
            (Int32)LzmaSpeed.Fastest,
            "bt4",
            true,
        };
    }


    private void Compress(string filePath, string compressedFilePath)
    {
        //Get the bytes of the file
        byte[] fileInBytes = File.ReadAllBytes(filePath);

        //Setup the encoder
        SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
        encoder.SetCoderProperties(SevenZipCoderProperties.PropertyNames, SevenZipCoderProperties.PropertyValues);

        using (MemoryStream outStream = new MemoryStream())
        {
            encoder.WriteCoderProperties(outStream);

            //Get the file bytes into a memory then compress them
            using (MemoryStream inStream = new MemoryStream(fileInBytes))
            {
                long uncompressedFilesize = inStream.Length;

                for (int i = 0; i < 8; i++)
                        outStream.WriteByte((Byte)(uncompressedFilesize >> (8 * i)));

                encoder.Code(inStream, outStream, -1, -1, null);
            }

            //Write the compressed file
            compressedFileSize = outStream.Length;
            using (FileStream file = new FileStream(compressedFilePath, FileMode.Create, FileAccess.Write))
            {
                outStream.WriteTo(file);
            }
        }
    }
}

Solution

  • ICodeProgress is an inteface so you need to implement it somewhere. You can implement the ICodeProgress interface in your class and pass this instead of null.

    For example, you would do something like this:

    class CompressorThreads : CompressorClassEvents, ICodeProgress
    {
        void ICodeProgress.SetProgress(long inSize, long outSize)
        {
            System.Diagnostics.Debug.WriteLine("processedInSize:" + inSize + "  processedOutSize:" + outSize);
        }
        private void Compress(string filePath, string compressedFilePath)
        {
            . . .
            encoder.Code(inStream, outStream, -1, -1, this);
            . . .
        }
    }