Blog dedicado a la programación .NET y la informática en general

Entradas etiquetadas como ‘SevenZipSharp’

Usar compresión SevenZipSharp en .NET

Tengo un programa para hacer las publicaciones de mis proyectos, este tiene la opción de hacer una copia de seguridad de los ficheros modificados, pero no los comprime.

Hoy voy a explicar cómo usar en .NET el que para mí es el mejor compresor de ficheros, 7zip, el cual además de tener mejor resultados en compresión también es el más rápido.

Introducción a la compresión en .NET

Inicialmente desde la versión 2.0 de Framework, Microsoft nos ofrecía en la librería System.IO.Compression las clases para comprimir DeflateStream y GZipStream.

Las diferencia fundamental entre estas clases radica en que GZipStream originalmente usa el algoritmo de DeflateStream pero se puede extender para que utilice otros formatos de compresión.

Hay un montón de ejemplos en internet, el problema fundamental es a la hora de comprimir una carpeta entera, así que os dejo el ejemplo más completo que he encontrado aquí.

La mayoría de la gente usa otras librerías de terceros como DotNetZip o también SharpZipLib, que son mucho más fácil de manejar y de la que hay también mucha información en Internet.

Pero como bien he dicho al principio de este artículo yo me quedo con el algoritmo LMZA que usa 7zip.

Paquete de Desarrollo de Software LMZA

El creador de 7zi,p Igor Pavlov, muy amablemente nos ha dejado un SDK de LMZA donde tiene un ejemplo para comprimir 1 sólo archivo. Con lo cual no hacemos mucho.

Buscando por Internet nos encontramos con nuestros amigos de CodePlex, que comparten con todos nosotros un paquete de código abierto llamado SevenZipSharp. Esta va a ser la librería que usemos en este artículo. Y la cual nos facilitará la vida para la compresión y descompresión. Por tanto nos descargamos su librería.

Ejemplo

El código que se va a mostrar consta de una solución hecha con VS2010 y un proyecto Windows Forms, tal y como se muestra en la siguiente imagen:

ExploradorSolucion

Consta de un formulario Windows y la librería 7z.dll de la cual hablaremos más adelante. Además se agregará la referencia a la librería de SevenZipSharp.

El formulario tiene la siguiente pinta:

Programa

El formulario básicamente toma un directorio del cuadro de texto y lo comprime con el mismo nombre del directorio y con la extensión 7z.

Para ello he quiero añadirle una barra de progreso que nos indique lo que queda por comprimir, ya que la librería facilita este uso.

Por tanto nos vemos en la necesidad de usar la clase BackgroundWorker, donde no me voy a extender mucho en su explicación.

Por tanto cuando se presiona el botón “Comprimir”, iniciaremos el control de ejecución en segundo plano para controlar el avance de la compresión.

private void button2_Click(object sender, EventArgs e)
{
    if (Directory.Exists(this.textBox1.Text))
    {
        progressBar1.Value = 0;
        object[] parametros = new object[] { this.textBox1.Text };
        backgroundWorker1.RunWorkerAsync(parametros);
    }
    else
    {
        MessageBox.Show("El directorio no existe");
    }
}

El componente BackgroundWorker iniciará la compresión:

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    string ficheroSalida = string.Format("{0}.7z", (string)((object[])e.Argument)[0]);
    try
    {
        comp.CompressDirectory((string)((object[])e.Argument)[0], ficheroSalida, true);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

El objeto “comp” es el objeto de la clase SevenZipCompressor que se ha inicializado en el constructor de la clase:

public FormPrueba()
{
    InitializeComponent();
    // Para que funcione correctamente se debe indicar la ruta a la librería 7z.dll, 
    // aqui lo que hago es incluirla en el proyecto y al estar en el mismo directorio no hace falta decírselo
    //string rutaLib = string.Format("{0}\\7z.dll", Application.StartupPath);
    //SevenZipCompressor.SetLibraryPath(rutaLib);
    comp = new SevenZipCompressor();
    comp.CompressionFinished += new EventHandler<EventArgs>(comp_CompressionFinished);
    comp.Compressing += new EventHandler<ProgressEventArgs>(comp_Compressing);
}

Además se están controlando los eventos de finalización y compresión de la clase SevenZipCompressor. De tal forma que al finalizar el proceso mostraremos al usuario un mensaje diciendo que ha finalizado. Y a medida que se van comprimiendo los ficheros usaremos la barra de progreso del formulario con el siguiente código:

void comp_Compressing(object sender, ProgressEventArgs e)
{
    try
    {
        backgroundWorker1.ReportProgress(e.PercentDone);
    }
    catch (Exception ex)
    {
        string parada = ex.Message;
    }
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

Lo único que cabe destacar es la inclusión de la librería de 7zip dentro del proyecto. Esto se debe a que de otra forma tenemos que indicar a la librería SevenZip la ruta de la misma, y de esta forma la encuentra directamente en el directorio de compilación. Para ello recordar que cuando se incluya la librería en el proyecto debes indicarle que se copie en el directorio de resultados.


PropiedadesDll

También tener en cuenta si la versión de instalación de 7zip en vuestro equipo, ya que yo tengo la de 64bit y esto al combinarlo con el proyecto da un error, para ello he tenido que usar la librería de 32bit que os podéis descargar también desde la web.

La solución, por supuesto comprimida con 7zip, la podéis descargar desde aquí el fichero con el nombre “2010WinForm_ComprimiendoFicherosSolution.7z”.

Espero que os sirva de ayuda.

Anuncios