使用LZMA算法(转载)



转自 逆时针 :

7-Zip 简介

7-Zip 是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的 7z 文件格式,而且还支持各种其它压缩文件格式,其中包括 ZIP, RAR, CAB, GZIP, BZIP2和 TAR 等等。此软件压缩的压缩比要比普通 ZIP 文件高 30-50% ,因此,它可以把 Zip 格式的文件再压缩 2-10% 。
7-Zip 主要特征
更新了算法来加大 7z 格式 的压缩比
支持格式:
压缩及解压缩:7z、ZIP、GZIP、BZIP2 和 TAR
仅解压缩:RAR、CAB、ISO、ARJ、LZH、CHM、WIM、Z、CPIO、RPM、DEB 和 NSIS
对于 ZIP 及 GZIP 格式,7-Zip 能提供比使用 PKZip 及 WinZip 高 2-10% 的压缩比
7z 格式支持创建自释放(SFX)压缩档案
集成 Windows 外壳扩展
强大的的文件管理
强大的命令行版本
支持 FAR Manager 插件
支持 69 种语言

C#中压缩/解压缩7-zip文件的方法

 1.控制台方式调用7z.exe文件

public static void Unzip(DirectoryInfo DirecInfo)
{
   if (DirectInfo.Exists)
   {
       foreach (FileInfo fileInfo in DirecInfo.GetFiles("*.zip"))
       {
           Process process = new Process();
           process.StartInfo.FileName = @"C:\Program Files\7-zip\7z.exe";
           process.StartInfo.Arguments = @" e C:\Directory\" + fileInfo.Name + @" -o C:\Directory";
           process.Start();
       }
   }
}

2.根据压缩算法LZMA SDK

LZMA SDK里面包括了压缩和解压缩算法的C#源码(当前版本是4.65)
下载地址: Download 7-Zip from SourceForge.net
 
3.在.NET应用程序中使用7-Zip的压缩/解压缩功能(作者 Abel Avram 译者 赵劼 )
开发人员Eugene Sichkar创建了一系列7-Zip动态链接库的C#接口,.NET应用程序中使用7-Zip的压缩/解压缩功能了。
据Eugene称,该项目实现了以下接口:
 
  • IProgress - 基本进度的回调
  • IArchiveOpenCallback - 打开压缩包的回调
  • ICryptoGetTextPassword - 为压缩提示密码的回调
  • IArchiveExtractCallback - 对压缩包进行解压的回调
  • IArchiveOpenVolumeCallback - 打开额外压缩卷的回调
  • ISequentialInStream - 基本的只读数据流接口
  • ISequentialOutStream - 基本的只写数据流的接口
  • IInStream - 可以随机读取的输入数据流接口
  • IOutStream - 输出数据流接口
  • IInArchive - 主要压缩接口
具体的使用方式可以参考源码中示例.
4.SevenZipSharp 
 

markhor 创建了SevenZipSharp 项目,SevenZipSharp 是开源的,里面实现了自解压和压缩所有7-ZIP支持的格式.它改进了7-Zip动态链接库的C#接口的一些方法.

常用压缩/解压缩示例(引自SevenZipSharp示例文件):
 

解压缩文件

 
using (SevenZipExtractor tmp = new SevenZipExtractor(@"d:\Temp\7z465_extra.7z")) 
{                
     for (int i = 0; i < tmp.ArchiveFileData.Count; i++) 
     { 
        tmp.ExtractFiles(@"d:\temp\!Пусто\", tmp.ArchiveFileData[i].Index); 
     } 
     //tmp.ExtractFiles(@"d:\temp\!Пусто\", 1, 3, 5); 
}

分卷压缩

SevenZipExtractor.SetLibraryPath(@"d:\Work\Misc\7zip\9.04\CPP\7zip\Bundles\Format7zF\7z.dll"); 
using (SevenZipExtractor tmp = new SevenZipExtractor(@"d:\Temp\SevenZip.7z.001")) 
{                 
    tmp.ExtractArchive(@"d:\Temp\!Пусто"); 
}

 压缩文件

SevenZipCompressor tmp = new SevenZipCompressor();             
tmp.CompressFiles(@"d:\Temp\arch.7z", @"d:\Temp\log.txt"); 
tmp.CompressDirectory(@"c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\1033", @"D:\Temp\arch.7z");

压缩ZIP文件

SevenZipCompressor tmp = new SevenZipCompressor(); 
tmp.ArchiveFormat = OutArchiveFormat.Zip; 
tmp.CompressFiles(@"d:\Temp\arch.zip", @"d:\Temp\gpl.txt", @"d:\Temp\ru_office.txt");

多线程解压缩

Thread t1 = new Thread(() => 
{ 
    using (SevenZipExtractor tmp = new SevenZipExtractor(@"D:\Temp\7z465_extra.7z")) 
    { 
        tmp.FileExtractionStarted += new EventHandler<FileInfoEventArgs>((s, e) => 
        { 
            Console.WriteLine(String.Format("[{0}%] {1}", 
                e.PercentDone, e.FileInfo.FileName)); 
        }); 
        tmp.ExtractionFinished += new EventHandler((s, e) => { Console.WriteLine("Finished!"); }); 
        tmp.ExtractArchive(@"D:\Temp\t1"); 
    } 
}); 

Thread t2 = new Thread(() => 
{ 
    using (SevenZipExtractor tmp = new SevenZipExtractor(@"D:\Temp\7z465_extra.7z")) 
    { 
        tmp.FileExtractionStarted += new EventHandler<FileInfoEventArgs>((s, e) => 
        { 
            Console.WriteLine(String.Format("[{0}%] {1}", 
                e.PercentDone, e.FileInfo.FileName)); 
        }); 
        tmp.ExtractionFinished += new EventHandler((s, e) => { Console.WriteLine("Finished!"); }); 
        tmp.ExtractArchive(@"D:\Temp\t2"); 
    } 
}); 

t1.Start(); 
t2.Start(); 
t1.Join(); 
t2.Join();

多线程压缩

Thread t1 = new Thread(() => 
{ 
    SevenZipCompressor tmp = new SevenZipCompressor();              
    tmp.FileCompressionStarted += new EventHandler<FileNameEventArgs>((s, e) => 
    { 
        Console.WriteLine(String.Format("[{0}%] {1}", 
            e.PercentDone, e.FileName)); 
    }); 
    tmp.CompressDirectory(@"D:\Temp\t1", @"D:\Temp\arch1.7z"); 
 

});

Thread t2 = new Thread(() => 
{ 
    SevenZipCompressor tmp = new SevenZipCompressor(); 
    tmp.FileCompressionStarted += new EventHandler<FileNameEventArgs>((s, e) => 
    { 
        Console.WriteLine(String.Format("[{0}%] {1}", 
            e.PercentDone, e.FileName)); 
    }); 
    tmp.CompressDirectory(@"D:\Temp\t2", @"D:\Temp\arch2.7z"); 
}); 
t1.Start(); 
t2.Start(); 
t1.Join(); 
t2.Join(); 

//^^^^^^^^^^^^^^^^^^^^^^^

//^^^^^^^^^^^^^^^^^^^^^^^

以下转自其他地方

"LZMA,(Lempel-Ziv-Markov chain-Algorithm的缩写),是 2001年以来得到发展的一个数据压缩算法,它用于7-Zip归档工具中的 7z格式。它使用类似于LZ77的字典编码机制,在一般的情况下压缩率比bzip2为高,用于压缩的字典文件大小可达4GB。"
http://zh.wikipedia.org/wiki/LZMA

7-Zip官方页面:7-Zip  中文:Sparanoid
LZMA SDK页面:  http://7z.sparanoid.com/sdk.html

下面是使用LZMA算法的实例(SDK版本:7zip907)

以下转自yesaidu 文章:

unsigned longCompressFile(char *filein,char *fileout)

{

   bool dictionaryIsDefined =false;

   UInt32 dictionary = (UInt32)-1;

   UStringmf = L"BT4";

   UInt32 numThreads = 2/*(UInt32)-1*/;

 

   CMyComPtr<ISequentialInStream>inStream;

   CInFileStream *inStreamSpec = 0;

   inStreamSpec =new CInFileStream;

   inStream =inStreamSpec;

   if (!inStreamSpec->Open(GetSystemString(filein)))

   {

       // Error: can not open input file

       return 1;

   }

 

   CMyComPtr<ISequentialOutStream>outStream;

   COutFileStream *outStreamSpec =new COutFileStream;

   outStream =outStreamSpec;

   if (!outStreamSpec->Create(GetSystemString(fileout),true))

   {

       // Error: can not open output file

       return 1;

   }

NCompress::NLzma::CEncoder *encoderSpec =new NCompress::NLzma::CEncoder;

   CMyComPtr<ICompressCoder>encoder =encoderSpec;

 

   if (!dictionaryIsDefined)

       dictionary = 1 << 23;

 

   UInt32 pb = 2; // posStateBits

   UInt32 lc = 3; // litContextBits,  = 0; for 32-bit data

   UInt32 lp = 0; // litPosBits, = 2; for 32-bit data

   UInt32 algo = 1; // algorithm

   UInt32 fb = 128; // numFastBytes

   UInt32 mc = 16 + fb / 2;

   bool mcDefined = false;

 

   PROPID propIDs[] =

   {

       NCoderPropID::kDictionarySize,

       NCoderPropID::kPosStateBits,

       NCoderPropID::kLitContextBits,

       NCoderPropID::kLitPosBits,

       NCoderPropID::kAlgorithm,

       NCoderPropID::kNumFastBytes,

       NCoderPropID::kMatchFinder,

       NCoderPropID::kEndMarker,

       NCoderPropID::kNumThreads,

       NCoderPropID::kMatchFinderCycles,

   };

   const int kNumPropsMax =sizeof(propIDs) /sizeof(propIDs[0]);

   

   PROPVARIANTproperties[kNumPropsMax];

   for (intp = 0; p < 6; p++)properties[p].vt =VT_UI4;

properties[0].ulVal = (UInt32)dictionary;

   properties[1].ulVal = (UInt32)pb;

   properties[2].ulVal = (UInt32)lc;

   properties[3].ulVal = (UInt32)lp;

   properties[4].ulVal = (UInt32)algo;

   properties[5].ulVal = (UInt32)fb;

 

   properties[6].vt =VT_BSTR;

   properties[6].bstrVal = (BSTR)(constwchar_t *)mf;

 

   properties[7].vt =VT_BOOL;

   properties[7].boolVal =VARIANT_FALSE;

 

   properties[8].vt =VT_UI4;

   properties[8].ulVal = (UInt32)numThreads;

 

   // it must be last in property list

   properties[9].vt =VT_UI4;

   properties[9].ulVal = (UInt32)mc;

 

   int numProps = kNumPropsMax;

   if (!mcDefined)numProps--;

 

   if (encoderSpec->SetCoderProperties(propIDs,properties,kNumPropsMax) !=S_OK)

   {

       //throw "Incorrect command";

       return 1;

   }

 

   encoderSpec->WriteCoderProperties(outStream);

UInt64fileSize = (UInt64)(Int64)-1;

   inStreamSpec->File.GetLength(fileSize);

 

   for (inti = 0; i < 8; i++)

   {

       BYTE b = BYTE(fileSize >> (8 *i));

       if (outStream->Write(&b,sizeof(b), 0) !=S_OK)

       {

           // Write error

           return 1;

       }

   }

 

   HRESULTresult =encoder->Code(inStream,outStream, 0, 0,0);

   if (result ==E_OUTOFMEMORY)

   {

       // Error: Can not allocate memory

       return 1;

   }  

   else if (result !=S_OK)

   {

       // Encoder error: result

       return 1;

   }

if (outStreamSpec !=NULL)

   {

       if (outStreamSpec->Close() !=S_OK)

       {

           // File closing error

           return 1;

       }

   }

 

   return 0;

} 

 

unsigned longUncompressFile(char *filein,char *fileout)

{

   CMyComPtr<ISequentialInStream>inStream;

   CInFileStream *inStreamSpec = 0;

   inStreamSpec =new CInFileStream;

   inStream =inStreamSpec;

   if (!inStreamSpec->Open(GetSystemString(filein)))

   {

       // Error: can not open input file

       return 1;

   }

   CMyComPtr<ISequentialOutStream>outStream;

   COutFileStream *outStreamSpec =NULL;

   outStreamSpec =new COutFileStream;

   outStream =outStreamSpec;

if (!outStreamSpec->Create(GetSystemString(fileout),true))

   {

       // Error: can not open output file

       return 1;

   }

 

   NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;

   CMyComPtr<ICompressCoder>decoder =decoderSpec;

   decoderSpec->FinishStream =true;

 

   const UInt32 kPropertiesSize = 5;

   Byte header[kPropertiesSize + 8];

   if (ReadStream_FALSE(inStream,header, kPropertiesSize + 8) !=S_OK)

   {

       // Read error

       return 1;

   }

   if (decoderSpec->SetDecoderProperties2(header,kPropertiesSize) !=S_OK)

   {

       // SetDecoderProperties error

       return 1;

   }

UInt64fileSize = 0;

   for (inti = 0; i < 8; i++)

       fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 *i);

 

   if (decoder->Code(inStream,outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) !=S_OK)

   {

       // Decoder error

       return 1;

   }

 

   if (outStreamSpec !=NULL)

   {

       if (outStreamSpec->Close() !=S_OK)

       {

           // File closing error

           return 1;

       }

   }

 

   return 0;

}

unsigned longCompressBuffer(unsignedchar *inBuffer,unsigned long inSize,

                        unsignedchar *outBuffer,unsigned long outSize,size_t *outSizeProcessed)

{

   bool dictDefined = false;

   UInt32 dict = (UInt32)-1;

 

   if ((inSize == 0) || (inBuffer == 0))return 1;

   if (/*(outSize == 0) || */(outBuffer == 0))return 1;

 

   Byte *outBuffer2 = 0;

   size_t outSize2;

 

   // we allocate 105% of original size for output buffer

   outSize2 = (size_t)inSize / 20 * 21 + (1 << 16); //fileSize / 20 * 21 + (1 << 16)

   if (outSize2 != 0)

   {

       outBuffer2 = (Byte *)MyAlloc((size_t)outSize2);

       if (outBuffer2 == 0)return 1;//throw "Can not allocate memory";

   }

 

   if (!dictDefined)dict = 1 << 23;

 

   *outSizeProcessed =outSize2;// !!

   int res = Lzma86_Encode(outBuffer2,outSizeProcessed,inBuffer,inSize,

                           5, dict,SZ_FILTER_AUTO);

if (res != 0)

   {

       // Encoder error = (int)res

       return 1;

   }

 

   memcpy(outBuffer,outBuffer2, *outSizeProcessed);

 

   MyFree(outBuffer2);

 

   return *outSizeProcessed == 0 ?1:0;

}

 

unsigned longUncompressBuffer(unsignedchar *inBuffer,unsigned long inSize,

                          unsignedchar *outBuffer,unsigned long outSize,size_t *outSizeProcessed)

{

   if ((inSize == 0) || (inBuffer == 0))return 1;

   if (/*(outSize == 0) || */(outBuffer == 0))return 1;

 

   Byte *outBuffer2 = 0;

   size_t outSize2;

 

   UInt64 outSize64;

   if (Lzma86_GetUnpackSize(inBuffer,inSize, &outSize64) != 0)

       return 1;//throw "data error";

   outSize2 = (size_t)outSize64;

   if (outSize2 !=outSize64)

       return 1;//throw "too big";

   if (outSize2 != 0)

   {

       outBuffer2 = (Byte *)MyAlloc(outSize2);

       if (outBuffer2 == 0)

           return 1;//throw "Can not allocate memory";

   }

 

   size_t inSize2 = inSize;

   *outSizeProcessed =outSize2;

   int res = Lzma86_Decode(outBuffer2,outSizeProcessed,inBuffer, &inSize2);

   if (inSize2 != (size_t)inSize)

       return 1;//throw "incorrect processed size";

   if (res != 0)

       return 1;//throw "LzmaDecoder error";

 

   memcpy(outBuffer,outBuffer2, *outSizeProcessed);

 

   MyFree(outBuffer2);

 

   return *outSizeProcessed == 0 ?1:0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值