Created
November 18, 2014 10:22
-
-
Save ststeiger/cb9750664952f775a341 to your computer and use it in GitHub Desktop.
LZMA-Compression with SevenZip SDK
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://www.nullskull.com/a/768/7zip-lzma-inmemory-compression-with-c.aspx | |
// http://www.7-zip.org/sdk.html | |
namespace SevenZip.Compression.LZMA | |
{ | |
public static class SevenZipHelper | |
{ | |
static int dictionary = 1 << 23; | |
// static Int32 posStateBits = 2; | |
// static Int32 litContextBits = 3; // for normal files | |
// UInt32 litContextBits = 0; // for 32-bit data | |
// static Int32 litPosBits = 0; | |
// UInt32 litPosBits = 2; // for 32-bit data | |
// static Int32 algorithm = 2; | |
// static Int32 numFastBytes = 128; | |
static bool eos = false; | |
static CoderPropID[] propIDs = | |
{ | |
CoderPropID.DictionarySize, | |
CoderPropID.PosStateBits, | |
CoderPropID.LitContextBits, | |
CoderPropID.LitPosBits, | |
CoderPropID.Algorithm, | |
CoderPropID.NumFastBytes, | |
CoderPropID.MatchFinder, | |
CoderPropID.EndMarker | |
}; | |
// these are the default properties, keeping it simple for now: | |
static object[] properties = | |
{ | |
(System.Int32)(dictionary), | |
(System.Int32)(2), | |
(System.Int32)(3), | |
(System.Int32)(0), | |
(System.Int32)(2), | |
(System.Int32)(128), | |
"bt4", | |
eos | |
}; | |
public static byte[] Compress(byte[] inputBytes) | |
{ | |
byte[] retVal = null; | |
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); | |
encoder.SetCoderProperties(propIDs, properties); | |
using (System.IO.MemoryStream strmInStream = new System.IO.MemoryStream(inputBytes)) | |
{ | |
using (System.IO.MemoryStream strmOutStream = new System.IO.MemoryStream()) | |
{ | |
encoder.WriteCoderProperties(strmOutStream); | |
long fileSize = strmInStream.Length; | |
for (int i = 0; i < 8; i++) | |
strmOutStream.WriteByte((byte)(fileSize >> (8 * i))); | |
encoder.Code(strmInStream, strmOutStream, -1, -1, null); | |
retVal = strmOutStream.ToArray(); | |
} // End Using outStream | |
} // End Using inStream | |
return retVal; | |
} // End Function Compress | |
public static byte[] Compress(string inFileName) | |
{ | |
byte[] retVal = null; | |
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); | |
encoder.SetCoderProperties(propIDs, properties); | |
using (System.IO.Stream strmInStream = new System.IO.FileStream(inFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) | |
{ | |
using (System.IO.MemoryStream strmOutStream = new System.IO.MemoryStream()) | |
{ | |
encoder.WriteCoderProperties(strmOutStream); | |
long fileSize = strmInStream.Length; | |
for (int i = 0; i < 8; i++) | |
strmOutStream.WriteByte((byte)(fileSize >> (8 * i))); | |
encoder.Code(strmInStream, strmOutStream, -1, -1, null); | |
retVal = strmOutStream.ToArray(); | |
} // End Using outStream | |
} // End Using inStream | |
return retVal; | |
} // End Function Compress | |
public static void Compress(string inFileName, string outFileName) | |
{ | |
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); | |
encoder.SetCoderProperties(propIDs, properties); | |
using (System.IO.Stream strmInStream = new System.IO.FileStream(inFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) | |
{ | |
using (System.IO.Stream strmOutStream = new System.IO.FileStream(outFileName, System.IO.FileMode.Create)) | |
{ | |
encoder.WriteCoderProperties(strmOutStream); | |
long fileSize = strmInStream.Length; | |
for (int i = 0; i < 8; i++) | |
strmOutStream.WriteByte((byte)(fileSize >> (8 * i))); | |
encoder.Code(strmInStream, strmOutStream, -1, -1, null); | |
strmOutStream.Flush(); | |
strmOutStream.Close(); | |
} // End Using outStream | |
} // End Using inStream | |
} // End Function Compress | |
public static byte[] Decompress(string inFileName) | |
{ | |
byte[] retVal = null; | |
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); | |
using (System.IO.Stream strmInStream = new System.IO.FileStream(inFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) | |
{ | |
strmInStream.Seek(0, 0); | |
using (System.IO.MemoryStream strmOutStream = new System.IO.MemoryStream()) | |
{ | |
byte[] properties2 = new byte[5]; | |
if (strmInStream.Read(properties2, 0, 5) != 5) | |
throw (new System.Exception("input .lzma is too short")); | |
long outSize = 0; | |
for (int i = 0; i < 8; i++) | |
{ | |
int v = strmInStream.ReadByte(); | |
if (v < 0) | |
throw (new System.Exception("Can't Read 1")); | |
outSize |= ((long)(byte)v) << (8 * i); | |
} //Next i | |
decoder.SetDecoderProperties(properties2); | |
long compressedSize = strmInStream.Length - strmInStream.Position; | |
decoder.Code(strmInStream, strmOutStream, compressedSize, outSize, null); | |
retVal = strmOutStream.ToArray(); | |
} // End Using newOutStream | |
} // End Using newInStream | |
return retVal; | |
} // End Function Decompress | |
public static void Decompress(string inFileName, string outFileName) | |
{ | |
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); | |
using (System.IO.Stream strmInStream = new System.IO.FileStream(inFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) | |
{ | |
strmInStream.Seek(0, 0); | |
using (System.IO.Stream strmOutStream = new System.IO.FileStream(outFileName, System.IO.FileMode.Create)) | |
{ | |
byte[] properties2 = new byte[5]; | |
if (strmInStream.Read(properties2, 0, 5) != 5) | |
throw (new System.Exception("input .lzma is too short")); | |
long outSize = 0; | |
for (int i = 0; i < 8; i++) | |
{ | |
int v = strmInStream.ReadByte(); | |
if (v < 0) | |
throw (new System.Exception("Can't Read 1")); | |
outSize |= ((long)(byte)v) << (8 * i); | |
} // Next i | |
decoder.SetDecoderProperties(properties2); | |
long compressedSize = strmInStream.Length - strmInStream.Position; | |
decoder.Code(strmInStream, strmOutStream, compressedSize, outSize, null); | |
strmOutStream.Flush(); | |
strmOutStream.Close(); | |
} // End Using newOutStream | |
} // End Using newInStream | |
} // End Function Decompress | |
public static byte[] Decompress(byte[] inputBytes) | |
{ | |
byte[] retVal = null; | |
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); | |
using (System.IO.MemoryStream strmInStream = new System.IO.MemoryStream(inputBytes)) | |
{ | |
strmInStream.Seek(0, 0); | |
using (System.IO.MemoryStream strmOutStream = new System.IO.MemoryStream()) | |
{ | |
byte[] properties2 = new byte[5]; | |
if (strmInStream.Read(properties2, 0, 5) != 5) | |
throw (new System.Exception("input .lzma is too short")); | |
long outSize = 0; | |
for (int i = 0; i < 8; i++) | |
{ | |
int v = strmInStream.ReadByte(); | |
if (v < 0) | |
throw (new System.Exception("Can't Read 1")); | |
outSize |= ((long)(byte)v) << (8 * i); | |
} // Next i | |
decoder.SetDecoderProperties(properties2); | |
long compressedSize = strmInStream.Length - strmInStream.Position; | |
decoder.Code(strmInStream, strmOutStream, compressedSize, outSize, null); | |
retVal = strmOutStream.ToArray(); | |
} // End Using newOutStream | |
} // End Using newInStream | |
return retVal; | |
} // End Function Decompress | |
} // End Class SevenZipHelper | |
} // End Namespace SevenZip.Compression.LZMA |
LZMA.Decompress(inStream, outStream [, Action<long, long> onProgress])
How I can assing this to a ProgressBar?
Like this for example:
var fileStream = File.OpenRead("..."); // Get Filestream to compress
var zipStream = File.Create("..."); // Output file
var totalSize = fileStream.Length; // <- Get filesize once
// Using IProgress<T> for notifying
var prg = new Progress<(long processedBytes, long resultSize)>();
prg.ProgressChanged += (s, e) =>
{
// Update UI / Progressbar, etc.
// \/ this writes "Compressing: 1.52%" \/
Console.WriteLine($"Compressing: {e.processedBytes / totalSize:p}");
};
// you can do this in Task.Run(() => ...) - Progress<T> will raise the event on the creation Thread
// pass IProgress to progress lambda, so that you can call "Report" on it
IProgress<(long processedBytes, long resultSize)> iprg = prg;
LZMA.Compress(fileStream, zipStream, LzmaSpeed.Fastest, DictionarySize.Medium,
(cur, max) => iprg.Report((cur, max)));
@kirides Can you explain how to use this SDK to extract the 7z file into a destination folder with individual files?
@kirides Can you explain how to use this SDK to extract the 7z file into a destination folder with individual files?
tldr: Not with this kind of code
7z files are different from LZMA/2 compressed files.
7z files are archives (like .zip)
whereas LZMA/2 compressed files are more like "something.gz", or "dir.tar.xz"
Great Code!. I am trying to compress a folder. But i dont find any doc to do it. Writing filesize#1, file content#1, filesize#2, file content#2 does not seem to work.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How I can assing this to a ProgressBar?