2011-01-26 17 views
6

Actualmente estoy trabajando con SharpZipLib bajo .NET 2.0 y por medio de esto necesito para comprimir un archivo único de un solo archivo comprimido. Con el fin de hacer esto actualmente estoy usando lo siguiente:SharpZipLib: La compresión de un único archivo en un único archivo comprimido

string tempFilePath = @"C:\Users\Username\AppData\Local\Temp\tmp9AE0.tmp.xml"; 
string archiveFilePath = @"C:\Archive\Archive_[UTC TIMESTAMP].zip"; 

FileInfo inFileInfo = new FileInfo(tempFilePath); 
ICSharpCode.SharpZipLib.Zip.FastZip fZip = new ICSharpCode.SharpZipLib.Zip.FastZip(); 
fZip.CreateZip(archiveFilePath, inFileInfo.Directory.FullName, false, inFileInfo.Name); 

Esto funciona exactamente (más o menos) como debe ser, sin embargo, mientras que las pruebas que he encontrado un Gotcha menor. Digamos que mi directorio temporal (es decir, el directorio que contiene el archivo de entrada no comprimido) contiene los siguientes archivos:

tmp9AE0.tmp.xml //The input file I want to compress 
xxx_tmp9AE0.tmp.xml // Some other file 
yyy_tmp9AE0.tmp.xml // Some other file 
wibble.dat // Some other file 

Cuando ejecuto la compresión de todos los archivos .xml están incluidas en el archivo comprimido. La razón de esto es debido al parámetro final fileFilter pasado al método CreateZip. Bajo el capó SharpZipLib está llevando a cabo una comparación de patrones y esto también recoge los archivos con el prefijo xxx_ y yyy_. Supongo que también recogería cualquier cosa postfijada.

Entonces la pregunta es, ¿cómo puedo comprimir un archivo único con SharpZipLib? Entonces, de nuevo, tal vez la pregunta es cómo puedo formatear ese fileFilter para que la coincidencia solo pueda recoger el archivo que quiero comprimir y nada más.

Como acotación al margen, ¿hay alguna razón de por qué no System.IO.Compression incluyen una clase ZipStream? (Sólo es compatible con GZipStream)

EDIT: Solución (Derivado de respuesta aceptada de Hans Passant)

Este es el método de compresión implementé:

private static void CompressFile(string inputPath, string outputPath) 
{ 
    FileInfo outFileInfo = new FileInfo(outputPath); 
    FileInfo inFileInfo = new FileInfo(inputPath); 

    // Create the output directory if it does not exist 
    if (!Directory.Exists(outFileInfo.Directory.FullName)) 
    { 
     Directory.CreateDirectory(outFileInfo.Directory.FullName); 
    } 

    // Compress 
    using (FileStream fsOut = File.Create(outputPath)) 
    { 
     using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(fsOut)) 
     { 
      zipStream.SetLevel(3); 

      ICSharpCode.SharpZipLib.Zip.ZipEntry newEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(inFileInfo.Name); 
      newEntry.DateTime = DateTime.UtcNow; 
      zipStream.PutNextEntry(newEntry); 

      byte[] buffer = new byte[4096]; 
      using (FileStream streamReader = File.OpenRead(inputPath)) 
      { 
       ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(streamReader, zipStream, buffer); 
      } 

      zipStream.CloseEntry(); 
      zipStream.IsStreamOwner = true; 
      zipStream.Close(); 
     } 
    } 
} 
+2

En cuanto a tu lado: ZipStream no tendría mucho sentido, ya que ZIP es un formato de archivo que puede contener más de un archivo. Supongo que podrían haber proporcionado una API completa para lectura y escritura y ZIP, pero obviamente habría sido mucho más esfuerzo que GZipStream. –

+0

En un aparte de la mía, ya que sólo se está comprimiendo un solo archivo, hay una razón por la que no desea utilizar simplemente la compresión gzip, que, como se nota, cuenta con el apoyo en el marco? –

+0

Me encantaría, podría hacer esto con un par de líneas de código. Tiene que ser postal como nuestra mesa de 'apoyo' no puede manejar las complejidades de gzip (hizo que el sonido sarcástico ??;)) – MrEyes

Respuesta

5

Este es un problema XY, simplemente don' usar FastZip. Siga el primer ejemplo en this web page para evitar accidentes.

+0

que funciona, sin embargo, el archivo comprimido incluye todos los directorios también. Sería mejor si el archivo solo contiene el archivo en el nivel raíz y nada más. – MrEyes

+1

cadena entryName = System.IO.Path.GetFileName (filename); –

Cuestiones relacionadas