2011-01-26 13 views
6

Attualmente sto lavorando con SharpZipLib sotto .NET 2.0 e tramite questo ho bisogno di comprimere un singolo file in un singolo archivio compresso. Per fare questo Attualmente sto usando il seguente:SharpZipLib: compressione di un singolo file in un singolo file compresso

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); 

Questo funziona esattamente (ish) come dovrebbe, tuttavia durante il test che ho incontrato un Gotcha minore. Diciamo che la mia directory temp (vale a dire la directory che contiene il file di input non compresso) contiene i seguenti file:

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 

Quando eseguo la compressione di tutti i file .xml sono incluse nell'archivio compresso. Il motivo è dovuto al parametro finale fileFilter passato al metodo CreateZip. Sotto il cofano SharpZipLib sta eseguendo un pattern match e questo preleva anche i file con prefisso xxx_ e yyy_. Presumo che raccolga anche qualcosa di postfixed.

Quindi la domanda è: come posso comprimere un singolo file con SharpZipLib? Poi di nuovo forse la domanda è come posso formattare quello fileFilter in modo che la corrispondenza possa sempre solo raccogliere il file che voglio comprimere e nient'altro.

Per inciso, c'è qualche ragione per cui System.IO.Compression non include una classe ZipStream? (Supporta solo GZipStream)

EDIT: Soluzione (Derivato da risposta accettata da Hans passant)

Questo è il metodo di compressione ho implementato:

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

Per quanto riguarda la tua parte: ZipStream non avrebbe molto senso, dal momento che ZIP è un formato di archivio che può contenere più di un file. Suppongo che avrebbero potuto fornire un'API completa per leggere e scrivere e ZIP, ma ovviamente sarebbe stato molto più impegnativo di GZipStream. –

+0

Come parte del mio, dato che stai comprimendo solo un singolo file, c'è una ragione per cui non vuoi usare solo la compressione GZip, che, come sai, ha un supporto all'interno del framework? –

+0

Mi piacerebbe, potrei farlo con un paio di righe di codice. Deve essere zip come la nostra scrivania di 'supporto' non può gestire la complessità di gzip (ha fatto sembrare sarcastico ??;)) – MrEyes

risposta

5

Questo è un problema di XY, appena don' t usare FastZip. Segui il primo esempio su this web page per evitare incidenti.

+0

Che funziona, tuttavia l'archivio compresso include anche tutte le directory. Sarebbe meglio se l'archivio contenga solo il file a livello di root e nient'altro. – MrEyes

+1

string entryName = System.IO.Path.GetFileName (nome file); –

Problemi correlati