// Project: Salient
// http://salient.codeplex.com
//
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
//
// Date: May 24 2010
#region
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.SharpZipLib.Zip;
#endregion
namespace Salient.IO.Compression
{
public static class DirectoryCompression
{
public static void CompressDirectory(this Stream target, string sourcePath,
Func<string, bool> excludeFromCompression)
{
sourcePath = Path.GetFullPath(sourcePath);
string parentDirectory = Path.GetDirectoryName(sourcePath);
int trimOffset = (string.IsNullOrEmpty(parentDirectory)
? Path.GetPathRoot(sourcePath).Length
: parentDirectory.Length);
List<string> fileSystemEntries = new List<string>();
fileSystemEntries
.AddRange(Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)
.Select(d => d + "\\"));
fileSystemEntries
.AddRange(Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories));
using (ZipOutputStream compressor = new ZipOutputStream(target))
{
compressor.SetLevel(9);
foreach (string filePath in fileSystemEntries)
{
if (excludeFromCompression(filePath))
{
continue;
}
compressor.PutNextEntry(new ZipEntry(filePath.Substring(trimOffset)));
if (filePath.EndsWith(@"\"))
{
continue;
}
byte[] data = new byte[2048];
using (FileStream input = File.OpenRead(filePath))
{
int bytesRead;
while ((bytesRead = input.Read(data, 0, data.Length)) > 0)
{
compressor.Write(data, 0, bytesRead);
}
}
}
compressor.Finish();
}
}
public static void DecompressToDirectory(this Stream source, string targetPath, string pwd,
Func<string, bool> excludeFromDecompression)
{
targetPath = Path.GetFullPath(targetPath);
using (ZipInputStream decompressor = new ZipInputStream(source))
{
if (!string.IsNullOrEmpty(pwd))
{
decompressor.Password = pwd;
}
ZipEntry entry;
while ((entry = decompressor.GetNextEntry()) != null)
{
if (excludeFromDecompression(entry.Name))
{
continue;
}
string filePath = Path.Combine(targetPath, entry.Name);
string directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
if (entry.IsDirectory)
{
continue;
}
byte[] data = new byte[2048];
using (FileStream streamWriter = File.Create(filePath))
{
int bytesRead;
while ((bytesRead = decompressor.Read(data, 0, data.Length)) > 0)
{
streamWriter.Write(data, 0, bytesRead);
}
}
}
}
}
}
}
Usage
using System;
using System.IO;
using NUnit.Framework;
using Salient.IO.Compression;
namespace CoreFiveConnector.Tests
{
[TestFixture]
public class Class1
{
[Test]
public void Test()
{
Func<string, bool> excludeFromCompression = path => { return false; };
MemoryStream compressed = new MemoryStream();
compressed.CompressDirectory("c:\\Temp", excludeFromCompression);
// sharpzip closes the target so we need to create a new seekable stream
MemoryStream compressed2 = new MemoryStream(compressed.ToArray());
Func<string, bool> excludeFromDecompression = path => { return false; };
compressed2.DecompressToDirectory("c:\\Temp2", null, excludeFromDecompression);
}
}
}