Skip to content

Instantly share code, notes, and snippets.

@dvhthomas
Created November 21, 2009 00:17
Show Gist options
  • Save dvhthomas/239906 to your computer and use it in GitHub Desktop.
Save dvhthomas/239906 to your computer and use it in GitHub Desktop.
7zip compression utility
using System;
using System.ComponentModel;
using System.IO;
using Woolpert.Common;
using Woolpert.Logging;
namespace Woolpert.Compression
{
/// <summary>
/// Zips up files and folders using 7-Zip, a command line tool with speed
/// </summary>
/// <remarks>Note that any directory paths supplied are interpreted
/// by 7z from it's executing location. So generally it's better to avoid
/// relative paths and just stick to fully qualified paths otherwise
/// you may be surprised at the eventual location of your outputs.</remarks>
public sealed class SevenZip : IZip
{
#region Private Fields
private readonly string _outputFormat;
private readonly string _sevenZipExecutablePath = ".\\7Zip\\7za.exe";
#endregion
#region Constructors
/// <summary>
/// Creates a new 7-Zip ready to zip files
/// </summary>
/// <remarks>By default it tries to find the 7z executable
/// alongside the assembly location. The default output format is
/// <see cref="SevenZipOutputFormat.SevenZip"/>.</remarks>
public SevenZip()
: this(".\\7za.exe")
{
}
/// <summary>
/// Creates a new compression utility with the default <see cref="SevenZipOutputFormat.SevenZip"/>
/// output format.
/// </summary>
/// <param name="sevenZipExecutablePath">Path to the 7-Zip stand alone file</param>
public SevenZip(string sevenZipExecutablePath) :
this(sevenZipExecutablePath, SevenZipOutputFormat.SevenZip)
{
}
/// <summary>
/// Creates a new compress file
/// </summary>
/// <param name="sevenZipExecutablePath"></param>
/// <param name="outputFormat"></param>
public SevenZip(string sevenZipExecutablePath, SevenZipOutputFormat outputFormat)
{
Log.For(this).Debug(string.Format("Initializing {0} with {1} format", GetType().Name,
Enum.GetValues(typeof(SevenZipOutputFormat)), outputFormat));
this._sevenZipExecutablePath = sevenZipExecutablePath;
this._outputFormat = Enumerations.Get(outputFormat);
}
#endregion
#region Public Methods
/// <summary>
/// Generates zip files using the 7-Zip on the command line. Blindingly fast
/// </summary>
/// <param name="zipFilePath">Path of zip file to create</param>
/// <param name="directoryToZip">The top level directory to zip up</param>
/// <param name="recursive">Would you like to zip up subdirectories as well?</param>
public void GenerateZipFile(string zipFilePath, string directoryToZip, bool recursive)
{
if (string.IsNullOrEmpty(zipFilePath) || string.IsNullOrEmpty(directoryToZip))
{
Log.For(this).Warn(
"Either you have left out a path to zip files to or the directory that you want to zip up. " +
string.Format("You specified {0} and {1} respectively. No files will be zipped.",
zipFilePath ?? "",
directoryToZip ?? ""
));
return;
}
if (Directory.Exists(directoryToZip))
{
Log.For(this).Info(string.Format("Using 7-Zip to zip up directory {0}.", directoryToZip));
string externalAppArgs = string.Format("a -t{0} \"{1}\" \"{2}\\*.*\" -r", _outputFormat, zipFilePath, directoryToZip);
if (!recursive)
{
externalAppArgs = string.Format("a -t{0} \"{1}\" \"{2}\\*.*\"", _outputFormat, zipFilePath, directoryToZip);
}
this.RunSevenZipCommand(externalAppArgs);
}
}
/// <summary>
/// Compress a single file
/// </summary>
/// <param name="zipFilePath">The archive file to create or overwrite</param>
/// <param name="fileToCompress">The single file to compress</param>
public void GenerateZipFile(string zipFilePath, FileInfo fileToCompress)
{
if (fileToCompress == null) throw new ArgumentNullException("fileToCompress");
if (string.IsNullOrEmpty(zipFilePath) || !fileToCompress.Exists)
{
Log.For(this).Error("Either the zip file target name is empty or " +
"the file to be compressed does not exist. Please check your input values.");
return;
}
DirectoryInfo zipFileLocation = new DirectoryInfo(zipFilePath);
DirectoryInfo parent = zipFileLocation.Parent;
if (parent != null) if (!parent.Exists) return;
// -m is an option argument, and x=9 means ultra compression.
var externalAppArgs = string.Format("a -t{0} \"{1}\" \"{2}\" -mx=9",
this._outputFormat,
zipFilePath,
fileToCompress.FullName);
this.RunSevenZipCommand(externalAppArgs);
}
/// <summary>
/// Extracts files from a zip archive
/// </summary>
/// <param name="zipFile">Path of the zip file to create or overwrite</param>
/// <param name="directoryToUnzipTo">The existing directory to put unzipped files into</param>
/// <remarks>The files extracted from the archive will be flattened; this means that
/// any directory structure within the archive will be lost. Also, any existing
/// files will the same name will be overwritten without asking.</remarks>
public void UnzipZipFile(string zipFile, string directoryToUnzipTo)
{
if (string.IsNullOrEmpty(zipFile) || string.IsNullOrEmpty(directoryToUnzipTo))
{
Log.For(this).Error("Either the zip file name is empty or " +
"the output directory name is empty. Please check your input values.");
return;
}
if (!File.Exists(zipFile))
{
Log.For(this).Info(string.Format("The zip file {0} does not exist", zipFile));
return;
}
var externalAppArgs = string.Format("e \"{0}\" -o\"{1}\" -aoa -y", zipFile, directoryToUnzipTo);
this.RunSevenZipCommand(externalAppArgs);
}
#endregion
#region Private/Protected Methods
/// <summary>
/// Executes the SevenZip command line with the parameters
/// created by one of the public methods.
/// </summary>
/// <param name="externalAppArgs"></param>
private void RunSevenZipCommand(string externalAppArgs)
{
Log.For(this).Info(string.Format("Calling external process {0} with arguments {1}.",
this._sevenZipExecutablePath,
externalAppArgs));
var exitCode = (SevenZipExitCodeType)ExternalApplication.RunCommandLine(
this._sevenZipExecutablePath
, externalAppArgs
, true
, true
);
if (exitCode != SevenZipExitCodeType.Success)
{
string error =
string.Format("7-Zip Utility had an error zipping up files. The reported error was {0}.",
Enum.GetName(typeof(SevenZipExitCodeType), exitCode));
Log.For(this).Error(error);
throw new ApplicationException(error);
}
}
#endregion
}
public enum SevenZipExitCodeType
{
Success = 0,
Warning = 1,
FatalError = 2,
CommandLineError = 7,
NotEnoughMemoryError = 8,
UserStoppedProcessingError = 255
}
public enum SevenZipOutputFormat
{
[Description("7z")]
SevenZip,
[Description("zip")]
Zip,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment