SharpZipLib: recursively zip/unzip directory structure
001
// Project: Salient
002
// http://salient.codeplex.com
003
//
004
// Copyright 2010, Sky Sanders <sky at skysanders.net>
005
// Dual licensed under the MIT or GPL Version 2 licenses.
007
//
008
// Date: May 24 2010
009
010
#region
011
012
using
System;
013
using
System.Collections.Generic;
014
using
System.IO;
015
using
System.Linq;
016
using
ICSharpCode.SharpZipLib.Zip;
017
018
#endregion
019
020
namespace
Salient.IO.Compression
021
{
022
public
static
class
DirectoryCompression
023
{
024
public
static
void
CompressDirectory(
this
Stream target,
string
sourcePath,
025
Func<
string
,
bool
> excludeFromCompression)
026
{
027
sourcePath = Path.GetFullPath(sourcePath);
028
029
string
parentDirectory = Path.GetDirectoryName(sourcePath);
030
031
int
trimOffset = (
string
.IsNullOrEmpty(parentDirectory)
032
? Path.GetPathRoot(sourcePath).Length
033
: parentDirectory.Length);
034
035
036
List<
string
> fileSystemEntries =
new
List<
string
>();
037
038
fileSystemEntries
039
.AddRange(Directory.GetDirectories(sourcePath,
"*"
, SearchOption.AllDirectories)
040
.Select(d => d +
"\\"
));
041
042
fileSystemEntries
043
.AddRange(Directory.GetFiles(sourcePath,
"*"
, SearchOption.AllDirectories));
044
045
046
using
(ZipOutputStream compressor =
new
ZipOutputStream(target))
047
{
048
compressor.SetLevel(9);
049
050
foreach
(
string
filePath
in
fileSystemEntries)
051
{
052
if
(excludeFromCompression(filePath))
053
{
054
continue
;
055
}
056
057
compressor.PutNextEntry(
new
ZipEntry(filePath.Substring(trimOffset)));
058
059
if
(filePath.EndsWith(
@"\"
))
060
{
061
continue
;
062
}
063
064
byte
[] data =
new
byte
[2048];
065
066
using
(FileStream input = File.OpenRead(filePath))
067
{
068
int
bytesRead;
069
070
while
((bytesRead = input.Read(data, 0, data.Length)) > 0)
071
{
072
compressor.Write(data, 0, bytesRead);
073
}
074
}
075
}
076
077
compressor.Finish();
078
}
079
}
080
081
082
public
static
void
DecompressToDirectory(
this
Stream source,
string
targetPath,
string
pwd,
083
Func<
string
,
bool
> excludeFromDecompression)
084
{
085
targetPath = Path.GetFullPath(targetPath);
086
087
using
(ZipInputStream decompressor =
new
ZipInputStream(source))
088
{
089
if
(!
string
.IsNullOrEmpty(pwd))
090
{
091
decompressor.Password = pwd;
092
}
093
094
ZipEntry entry;
095
096
while
((entry = decompressor.GetNextEntry()) !=
null
)
097
{
098
if
(excludeFromDecompression(entry.Name))
099
{
100
continue
;
101
}
102
103
string
filePath = Path.Combine(targetPath, entry.Name);
104
105
string
directoryPath = Path.GetDirectoryName(filePath);
106
107
108
if
(!
string
.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
109
{
110
Directory.CreateDirectory(directoryPath);
111
}
112
113
if
(entry.IsDirectory)
114
{
115
continue
;
116
}
117
118
byte
[] data =
new
byte
[2048];
119
using
(FileStream streamWriter = File.Create(filePath))
120
{
121
int
bytesRead;
122
while
((bytesRead = decompressor.Read(data, 0, data.Length)) > 0)
123
{
124
streamWriter.Write(data, 0, bytesRead);
125
}
126
}
127
}
128
}
129
}
130
}
131
}
Usage
01
using
System;
02
using
System.IO;
03
using
NUnit.Framework;
04
using
Salient.IO.Compression;
05
06
namespace
CoreFiveConnector.Tests
07
{
08
[TestFixture]
09
public
class
Class1
10
{
11
[Test]
12
public
void
Test()
13
{
14
Func<
string
,
bool
> excludeFromCompression = path => {
return
false
; };
15
16
MemoryStream compressed =
new
MemoryStream();
17
18
19
compressed.CompressDirectory(
"c:\\Temp"
, excludeFromCompression);
20
21
22
// sharpzip closes the target so we need to create a new seekable stream
23
MemoryStream compressed2 =
new
MemoryStream(compressed.ToArray());
24
25
Func<
string
,
bool
> excludeFromDecompression = path => {
return
false
; };
26
27
compressed2.DecompressToDirectory(
"c:\\Temp2"
,
null
, excludeFromDecompression);
28
}
29
}
30
}