7Zip (LZMA) In-Memory Compression with C#
By Peter Bromberg
Shows a simple C# SevenZip.Compression.Lzma.SevenZipHelper class to enable high-compression of in-memory objects with C#. Adds a new 7Zip format LZMA Cookie Compression class to the previously published CookieCompression utility.
"The difference between a violin and a viola is that a viola burns longer." - Victor Borge
Many developers are familiar with 7-Zip and use it as an alternative to Winzip or Winrar. I use the Windows distribution of 7Zip frequently because of the higher compression ratios it provides, with an excellent balance between speed and high compression with the default settings.
However I would venture to guess that most developers are unaware that Igor Pavlov, the primary developer of SevenZip, provides a full SDK that includes his LZMA source code in several languages, including one in C#.
The C# code in the SDK is designed to be used in an executable with a command - line interface. However, by recompiling this to a class library, removing the command line parser classes, and adding a simple SevenZipHelper class that uses the default property settings, we can get a very handy and powerful class library for in-memory compression tasks.
Some facts on LZMA (7Zip) Compression:
- Average compression ratio of LZMA is about 30% better than that of gzip, and 15% better than that of bzip2.
- Decompression speed is only little slower than that of gzip, being two to five times faster than bzip2.
- In fast mode, 7Zip compresses faster than bzip2 with a comparable compression ratio.
- Achieving the best compression ratios takes four to even twelve times longer than with bzip2. However. this doesn't affect decompressing speed.
To illustrate the usefulness of this approach, I took the code from a previous article on compressing Http Cookies, and added another CompressedCookie class to it in which I use the 7zip library instead of the default System.IO.Compression deflate mode classes. With LZMA compression (the default for 7Zip), we can get a huge increase in the amount of data that can be stored in the 4,000 byte allowable maximum size for a cookie.
The downloadable Visual Studio 2005 Solution below includes the SevenZip C# LZMA classes, my SevenZipHelper "wrapper class", and a reconstructed CompressedCookies Web application illustrating it's use.
Using my "Helper" class is utterly simple:
The static Compress Method:
byte[] SevenZip.Compression.LZMA.SevenZipHelper.Compress( byte[] )
The static Decompress Method:
byte[] SevenZip.Compression.LZMA.SevenZipHelper.Decompress( byte[] )
I don't think it could be made much simpler!
The new LZMA Cookie Compression class:
using System.Text;
using System.Web;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using SevenZip.Compression.LZMA;
namespace CompressedCookies
{
public static class CpCookiesLzma
{
public static int Set(string cookieName, object cookieValue, DateTime expirationDate)
{
int siz = 0;
try
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, cookieValue);
byte[] inbyt = ms.ToArray();
byte[] b = SevenZip.Compression.LZMA.SevenZipHelper.Compress(inbyt);
string sCookieVal = Convert.ToBase64String(b);
HttpCookie cook = new HttpCookie(cookieName);
cook.Value = sCookieVal;
siz = sCookieVal.Length;
cook.Expires = expirationDate;
HttpContext.Current.Response.Cookies.Add(cook);
}
catch
{
throw ;
}
return siz;
}
public static object Get(string cookieName)
{
object retval = null;
try
{
byte[] bytCook = Convert.FromBase64String(HttpContext.Current.Request.Cookies[cookieName].Value);
byte[] outByt = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(bytCook);
MemoryStream outMs = new MemoryStream(outByt);
outMs.Seek(0, 0);
BinaryFormatter bf = new BinaryFormatter();
retval = (object)bf.Deserialize(outMs, null);
}
catch(Exception ex)
{
throw ex;
}
return retval;
}
public static bool Delete(string cookieName)
{
bool retval = true;
try
{
HttpContext.Current.Request.Cookies[cookieName].Expires = DateTime.Now.AddDays(-365);
}
catch
{
retval = false;
}
return retval;
}
}
}
The download below includes the LZMA (7Zip) C# class library project, which includes my SevenZipHelper class, the Compressed Cookies class library project with the addition of the CpCookieLzma class with 7Zip, and a web application that illustrates it's use for compressed cookie operation. Of course, the 7Zip library can be used for any general compression need.
NOTE: If you get any "out of memory" errors using this, try reducing the size of the dictionary in the SevenZipHelper class (e.g. <<21 instead of << 23).
Download the Visual Studio 2005 Solution accompanying this article.
Popularity (25054 Views)
 |
| Biography - Peter Bromberg |
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites.
|  |
|
|
Article Discussion: 7Zip (LZMA) In-Memory Compression with C#
Including SevenZipHelper in my project
Nicolas Ronvel replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
Hi ! I found your SevenZipHelper code really useful, and I use it in my project for creating compressed file packages. I planned to put my project under the GNU GPL License. Can I use the dll you provided for SevenZipHelper ? What kind of text license do I need to add to use It ?
Thanks !
All code on eggheadcafe.com is in the public domain
Peter Bromberg replied
to Nicolas Ronvel at Wednesday, January 17, 2007 3:45 PM
unless otherwise stated. Attrbution to the author is a courtesy, but not required. Good luck with your project.
Thanks
Nicolas Ronvel replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
OK. Thanks. I put a link to this page into the readme file.
System.OutOfMemoryException error
S Hanslope replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
Thank you for providing this article it was exactly what I was looking for. I tested it all on a development environment (.net v2, XP) and everything worked fine. I then tested it on a server environment, (,net v2, windows server 2003 enterprise) but it immediately failed with the following error:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at SevenZip.Compression.LZ.BinTree.Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) at SevenZip.Compression.LZMA.Encoder.Create() at SevenZip.Compression.LZMA.Encoder.SetStreams(Stream inStream, Stream outStream, Int64 inSize, Int64 outSize) at SevenZip.Compression.LZMA.Encoder.Code(Stream inStream, Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) at SevenZip.Compression.LZMA.SevenZipHelper.Compress(Byte[] inputBytes) at CompressedCookies.CpCookiesLzma.Set(String cookieName, Object cookieValue, DateTime expirationDate)
The website hosted on this server continued to work correctly and all other aspx pages were still functioning correctly. Are you able to give any pointers as to what might have caused this?

Could be a bug in the Managed 7zip code.
Peter Bromberg replied
to S Hanslope at Wednesday, January 17, 2007 3:45 PM
I've seen this on occasion. I'll take a look at it, the seven zip comes from the SDK and is not my code. Also, it could be that you are attempting to compress more data than a cookie can hold.
Also, try reducing the size of the dictionary in the SevenZipHelper class:
static int dictionary = 1 << 21;
Re: Could be a bug in the Managed 7zip code.
S Hanslope replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
Thank you for the response. Just on your first point, its definitely not the size of the data, I am only testing it with about 30 characters.
Were you able to solve this issue?
Hi,
I am using LZMA in my windows app. Randomly, it throws the same outofmemory exception. Were you able to solve this issue? If yes, can you help me out with the solution?
Thanks.
Ned replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
I took the project and converted it to Visual Studio 2008 and when I run it, the cookies do not persist to the target page when the response.redirect is used.
If I change over to
Server.Transfer("Target.aspx", false);
then things work very well. I realize the article is a few years old, but I was curious as to why things appear to be different in VS 2008 versus the previous version?
Pyraman replied
to Nicolas Ronvel at Wednesday, January 17, 2007 3:45 PM
I used SevenZipHelper to compress a .jpeg file. The result is not so good.
byte[] DataBytes = File.ReadAllBytes("frame0.jpg");
label1.Text = (DataBytes.Length).ToString() + " bytes";
byte[] compressed = SevenZip.Compression.LZMA.SevenZipHelper.Compress(DataBytes);
label2.Text = (compressed.Length).ToString() + " bytes";
Result:
label1 display 14509 bytes
label2 display 14443 bytes.
Is it efficient to use SevenZipHelper to compress image format files?
Timothy replied
to Pyraman at Wednesday, January 17, 2007 3:45 PM
I am guessing the jpeg format is already compressed down pretty well...would probably work better on .bmp or maybe png files...but I guess most image formats already offer compression...
Andrew replied
to Timothy at Wednesday, January 17, 2007 3:45 PM
7zip is overcomplicated. Counter-example is iROLZ by Andrew Polar. http://www.ezcodesample.com/rolz/rolz_article.html
It shows that by 500 lines C# code you can approach efficiency of 7zip. It is a little-bit off on compression but faster in speed.
mohammad replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
hi. i want to make a program with matlab that uses lzma algorithm. but i have not find anything useful in internet and some books. do you know where i can finde something useful? somehtings like simple esapmles and algorithm
Peter Bromberg replied
to Andrew at Wednesday, January 17, 2007 3:45 PM
apoorv replied
to Peter Bromberg at Wednesday, January 17, 2007 3:45 PM
hi
i am using your compression to upload data through webservice.
i see that in my dual core processor the cup usage of one core is 100% while 2nd core is idle ..
how to make this compression / decompression run in multithread
please help
7Zip (LZMA) In-Memory Compression with C#Shows a simple C# SevenZip.Compression.Lzma.SevenZipHelper class to enable high-compression of in-memory objects with C#. Adds a new 7Zip format LZMA Cookie Compression class to the previously published CookieCompression utility.