LZH在字节数组中解压缩?

时间:2016-01-03 14:37:10

标签: archive memorystream compression lzh

LZH存档嵌入在文件中。该文件被读入byte [],LZH部分被识别为较小的字节[]。

如何使用.NET Framework 4.6(C#)将嵌入的LZH字节解压缩到另一个byte []?我只看到http://www.infoq.com/news/2008/06/7-Zip-from-.NET并没有完全符合我的需要。

感谢。

1 个答案:

答案 0 :(得分:1)

以下代码片段取自本文的示例程序 http://www.codeproject.com/Articles/27148/C-NET-Interface-for-Zip-Archive-DLLs

没有重大变化:它不是读写文件,而是读写字节数组。更改以评论标记 以sevenzip.exe e "C:\temp\gwo0.11-sample-win32.lzh" 3为例运行

https://dl.dropboxusercontent.com/u/71459360/7z.zip

using System;
using System.Collections.Generic;
using System.Text;
using Nomad.Archive.SevenZip;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;

namespace SevenZip
{
    class Program
    {
        private static void ShowHelp()
        {
            Console.WriteLine("SevenZip");
            Console.WriteLine("SevenZip l {ArchiveName}");
            Console.WriteLine("SevenZip e {ArchiveName} {FileNumber}");
        }

        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                ShowHelp();
                return;
            }

            try
            {
                string ArchiveName;
                uint FileNumber = 0xFFFFFFFF;
                bool Extract;

                switch (args[0])
                {
                    case "l":
                        ArchiveName = args[1];
                        Extract = false;
                        break;
                    case "e":
                        ArchiveName = args[1];
                        Extract = true;
                        if ((args.Length < 3) || !uint.TryParse(args[2], out FileNumber))
                        {
                            ShowHelp();
                            return;
                        }
                        break;
                    default:
                        ShowHelp();
                        return;
                }

                using (SevenZipFormat Format = new SevenZipFormat(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll")))
                {
                    IInArchive Archive = Format.CreateInArchive(SevenZipFormat.GetClassIdFromKnownFormat(KnownSevenZipFormat.Lzh));
                    if (Archive == null)
                    {
                        ShowHelp();
                        return;
                    }

                    try
                    {
                        //the byte array is provided by you. here it's coming from a file
                        byte[] data;
                        using (var stream = File.OpenRead(ArchiveName))
                        {
                            data = new byte[stream.Length];
                            stream.Read(data, 0, data.Length);
                        }

                        using (InStreamWrapper ArchiveStream = new InStreamWrapper(new MemoryStream(data))) //modified here
                        {
                            ulong CheckPos = 32 * 1024;
                            if (Archive.Open(ArchiveStream, ref CheckPos, null) != 0)
                                ShowHelp();

                            Console.Write("Archive: ");
                            Console.WriteLine(ArchiveName);

                            if (Extract)
                            {
                                PropVariant Name = new PropVariant();
                                Archive.GetProperty(FileNumber, ItemPropId.kpidPath, ref Name);
                                string FileName = (string) Name.GetObject();

                                Console.Write("Extracting: ");
                                Console.Write(FileName);
                                Console.Write(' ');

                                MemoryStream ms = new MemoryStream();
                                Archive.Extract(new uint[] { FileNumber }, 1, 0, new ArchiveMemoryCallback(FileNumber, ms)); //modified here
                                byte[] output = ms.ToArray(); //here you have the output byte array
                                output.ToString();
                            }
                            else
                            {
                                Console.WriteLine("List:");
                                uint Count = Archive.GetNumberOfItems();
                                for (uint I = 0; I < Count; I++)
                                {
                                    PropVariant Name = new PropVariant();
                                    Archive.GetProperty(I, ItemPropId.kpidPath, ref Name);
                                    Console.Write(I);
                                    Console.Write(' ');
                                    Console.WriteLine(Name.GetObject());
                                }
                            }
                        }
                    }
                    finally
                    {
                        Marshal.ReleaseComObject(Archive);
                    }
                }
            }
            catch (Exception e)
            {
                Console.Write("Error: ");
                Console.WriteLine(e.Message);
            }
        }
    }

    class ArchiveCallback : IArchiveExtractCallback
    {
        private uint FileNumber;
        private string FileName;
        private OutStreamWrapper FileStream;

        public ArchiveCallback(uint fileNumber, string fileName)
        {
            this.FileNumber = fileNumber;
            this.FileName = fileName;
        }

        #region IArchiveExtractCallback Members

        public void SetTotal(ulong total)
        {
        }

        public void SetCompleted(ref ulong completeValue)
        {
        }

        public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
        {
            if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
            {
                string FileDir = Path.GetDirectoryName(FileName);
                if (!string.IsNullOrEmpty(FileDir))
                    Directory.CreateDirectory(FileDir);
                FileStream = new OutStreamWrapper(File.Create(FileName));

                outStream = FileStream;
            }
            else
                outStream = null;

            return 0;
        }

        public void PrepareOperation(AskMode askExtractMode)
        {
        }

        public void SetOperationResult(OperationResult resultEOperationResult)
        {
            FileStream.Dispose();
            Console.WriteLine(resultEOperationResult);
        }

        #endregion
    }


    //new
    class ArchiveMemoryCallback : IArchiveExtractCallback
    {
        private uint FileNumber;
        private Stream stream;
        private OutStreamWrapper FileStream;

        public ArchiveMemoryCallback(uint fileNumber, Stream stream)
        {
            this.FileNumber = fileNumber;
            this.stream = stream;
        }

        #region IArchiveExtractCallback Members

        public void SetTotal(ulong total)
        {
        }

        public void SetCompleted(ref ulong completeValue)
        {
        }

        public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
        {
            if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
            {
                FileStream = new OutStreamWrapper(stream);

                outStream = FileStream;
            }
            else
                outStream = null;

            return 0;
        }

        public void PrepareOperation(AskMode askExtractMode)
        {
        }

        public void SetOperationResult(OperationResult resultEOperationResult)
        {
            FileStream.Dispose();
            Console.WriteLine(resultEOperationResult);
        }

        #endregion
    }
}