Obecnie pracuję z SharpZipLib pod .NET 2.0 i przez to muszę skompresować pojedynczy plik do jednego skompresowanego archiwum. W tym celu Obecnie używam następujący:SharpZipLib: Kompresowanie pojedynczego pliku do pojedynczego skompresowanego pliku
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);
Działa to dokładnie (ish) jak powinien, jednak podczas testów jakie napotkałem niewielki Gotcha. Powiedzmy, że mój katalog temp (czyli katalog zawierający plik wejściowy nieskompresowany) zawiera następujące pliki:
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
Kiedy biegnę kompresję wszystkich .xml
pliki są zawarte w skompresowanym archiwum. Powodem tego jest ostateczny parametr fileFilter
przekazany do metody . Pod maską SharpZipLib przeprowadza dopasowanie do wzorca, a także podnosi pliki z prefiksem xxx_
i yyy_
. Zakładam, że to również wykryłoby wszystko, co jest postfiksowane.
Pytanie brzmi: jak skompresować pojedynczy plik za pomocą SharpZipLib? Być może znowu pytanie brzmi: jak mogę sformatować ten fileFilter
, aby mecz mógł tylko pobrać plik, który chcę skompresować i nic więcej.
Na marginesie, czy istnieje powód, dla którego System.IO.Compression
nie obejmuje klasy ? (Obsługuje tylko GZipStream)
EDIT: Rozwiązanie (pochodzący z przyjętą odpowiedzi od Hans Passant)
Jest to metoda kompresji I wdrożone:
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();
}
}
}
Co do boku: ZipStream nie miałoby sensu, ponieważ ZIP jest formatem archiwum, w którym można przechowywać więcej niż jeden plik. Przypuszczam, że mogliby zapewnić pełne API do czytania i pisania oraz ZIP-ów, ale oczywiście byłby to o wiele większy wysiłek niż GZipStream. –
Moim zdaniem, kompresując tylko jeden plik, istnieje powód, dla którego nie chcesz używać kompresji GZip, która, jak możesz zauważyć, ma wsparcie w ramach? –
Chciałbym, mógłbym to zrobić z kilkoma liniami kodu. Musi to być zip, ponieważ nasze "wsparcie" nie może obsłużyć złożoności gzip (czy to brzmi sarkastycznie?)). – MrEyes