473,386 Members | 1,674 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Compression in .NET 2.0

Hi There

Is there any easy way to use the System.Compression tools in .NET 2.0
to compress an entire directory ?

All my source code is kept in a single directory so I have written a
utility that recursively backs up the directory and compresses each
file as it goes. The utility has no GUI.

I have attached the program here, I would be interested to get any
feedback as I am still learning C#.

TIA
Bill


using System;

using System.Configuration;

using System.Diagnostics;

using System.IO;

using System.IO.Compression;

using System.Globalization;

namespace FileCopier

{

sealed public class FileCopierMain

{

public enum CompressionActions { Nothing, Compress, Decompress };

static string CompressSuffix = ".BWZIP";

static string ToFolder = @"C:\Backups\";

//************************************************** *

//TO BACKUP AND COMPRESS, COMMENT THIS IN

//AND SET THE FROM FOLDERS

static CompressionActions CompressionAction =
CompressionActions.Compress;

static string FromFolder = @"C:\Dev\";

//************************************************** *

//************************************************** *

//TO DECOMPRESS A BACKED UP FOLDER, COMMENT THIS IN

//AND SET THE FROM FOLDER EQUAL TO THE BACKED UP FOLDER

//static CompressionActions CompressionAction =
CompressionActions.Decompress;

//static string FromFolder = @"C:\Backups\Dev_30Jul05_3";

//************************************************** *

private FileCopierMain() { }

static void Main()

{

if (FromFolder.Substring(FromFolder.Length - 1, 1) == @"\")

FromFolder = FromFolder.Substring(0, FromFolder.Length - 1);

if (ToFolder.Substring(ToFolder.Length - 1, 1) == @"\")

ToFolder = ToFolder.Substring(0, ToFolder.Length - 1);
//Work out the folder which we are going to copy to. Do not overwrite
old backups

int LastBackSlashPos = FromFolder.LastIndexOf(@"\");

string NewFolderName = FromFolder.Substring(LastBackSlashPos + 1,
FromFolder.Length - LastBackSlashPos - 1);

NewFolderName += "_" + System.DateTime.Now.Date.ToString("ddMMMyy",
CultureInfo.CurrentCulture);

if (Directory.Exists(ToFolder + @"\" + NewFolderName))

{

int newFolderAppend = 1;

while (Directory.Exists(ToFolder + @"\" + NewFolderName + "_" +
newFolderAppend.ToString(CultureInfo.CurrentCultur e)))

{

newFolderAppend++;

}

NewFolderName += "_" +
newFolderAppend.ToString(CultureInfo.CurrentCultur e);

}

//Do the copy

CopyDirectory(FromFolder, ToFolder + @"\" + NewFolderName, true);

}

public static void CopyDirectory(string sourcePath, string
destinationPath, bool recurse)

{

String[] files;

if (destinationPath[destinationPath.Length - 1] !=
Path.DirectorySeparatorChar)

destinationPath += Path.DirectorySeparatorChar;

if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);

files = Directory.GetFileSystemEntries(sourcePath);

foreach (string element in files)

{

if (recurse)

{

// copy sub directories (recursively)

if (Directory.Exists(element))

CopyDirectory(element, destinationPath + Path.GetFileName(element),
recurse);

// copy files in directory

else

{

if (CompressionAction == CompressionActions.Compress)

BWCompressionUtility.CopyAndCompressFile(element, destinationPath +
Path.GetFileName(element) + CompressSuffix);

else if (CompressionAction == CompressionActions.Decompress)

BWCompressionUtility.CopyAndDecompressFile(element , destinationPath +
Path.GetFileName(element).Replace(CompressSuffix,s tring.Empty));

else

File.Copy(element, destinationPath + Path.GetFileName(element), true);

}

}

else

{

// only copy files in directory

if (!Directory.Exists(element))

{

if (CompressionAction == CompressionActions.Compress)

BWCompressionUtility.CopyAndCompressFile(element, destinationPath +
Path.GetFileName(element) + CompressSuffix);

else if (CompressionAction == CompressionActions.Decompress)

BWCompressionUtility.CopyAndDecompressFile(element , destinationPath +
Path.GetFileName(element).Replace(CompressSuffix, string.Empty));

else

File.Copy(element, destinationPath + Path.GetFileName(element), true);

}

}

}

}

}

public class BWCompressionUtility

{

//References

//http://www.codeguru.com/columns/DotNet/article.php/c9931

//http://groups.google.com.au/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/53ec661446a637a9/bb15f1069eb8e175?lnk=st&q=System.IO.Compression+Fo lder&rnum=1&hl=en#bb15f1069eb8e175

//http://msdn2.microsoft.com/library/as1ff51s(en-us,vs.80).aspx

/// <summary>

/// Private because all members are static

/// </summary>

private BWCompressionUtility() { }

public static void CopyAndCompressFile(string SourceFullPath, string
DestFullPath)

{

FileStream fs = null;

GZipStream compressedZipStream = null;

// Open and read the contents of the file

fs = new FileStream(SourceFullPath, FileMode.Open, FileAccess.Read,
FileShare.Read);

byte[] buffer = new byte[fs.Length];

int count = fs.Read(buffer, 0, buffer.Length);

if (count != buffer.Length)

throw new Exception("Unable to read data from file");

fs.Close();

// Write buffer to file

fs = new FileStream(DestFullPath, FileMode.Create);

compressedZipStream = new GZipStream(fs, CompressionMode.Compress,
true);

compressedZipStream.Write(buffer, 0, buffer.Length);

compressedZipStream.Close();

fs.Close();

return;

}

public static void CopyAndDecompressFile(string SourceFullPath, string
DestFullPath)

{

FileStream fsREAD = null;

FileStream fsWRITE = null;

GZipStream compressedZipStream = null;

//Compressed File to Read and Associated Stream

fsREAD = System.IO.File.OpenRead(SourceFullPath);

compressedZipStream = new GZipStream(fsREAD,
CompressionMode.Decompress);

//Decompressed File

fsWRITE = new FileStream(DestFullPath, FileMode.Create);

//Read through the stream and write it out

int bytesRead = 0;

int bytesToDecompress = 1000;

byte[] holdingBay = new byte[bytesToDecompress];

while ((bytesRead = compressedZipStream.Read(holdingBay, 0,
holdingBay.Length)) > 0)

fsWRITE.Write(holdingBay, 0, bytesRead);

//Close all streams

compressedZipStream.Close();

fsWRITE.Close();

fsREAD.Close();

}

}

}

Nov 17 '05 #1
3 4554
or*******@yahoo.com.au wrote:
Is there any easy way to use the System.Compression tools in .NET 2.0
to compress an entire directory ?
I think this is not currently possible, or rather you'd have to do it
yourself in large parts. The new classes under System.IO.Compression
provide only the ability to compress stream data, but they don't have
any of the functionality that's needed to handle multi-file management
information - such as the list of files in the archive, the hierarchy of
files and folders that may be included and so on. If you want that kind
of functionality, you'll be better off looking at SharpZipLib.
I have attached the program here, I would be interested to get any
feedback as I am still learning C#.


So, to a learner: nicely done! At a quick glance, one thing met my eye:
you are loading all the content of each file that you compress into a
memory buffer before writing it back out into the compressed stream. You
should try experimenting with having both streams open at the same time
and transferring content from one to the other buffer by buffer - that
way your algorithm will be a lot more efficient with large files.

Oliver Sturm
--
omnibus ex nihilo ducendis sufficit unum
Spaces inserted to prevent google email destruction:
MSN oliver @ sturmnet.org Jabber sturm @ amessage.de
ICQ 27142619 http://www.sturmnet.org/blog
Nov 17 '05 #2
Thanks Oliver, I implemented your suggestion and it runs 25% quicker on
compressions now.

I also added a couple of other features:
- It accepts command line parameters
- One of the command line parameters is to ignore BIN and OBJ folders

Here is the latest implementation. Btw - I arbitrarily chose an array
size of 1,000 .. I have not had time to experiment with different array
sizes yet.

Cheers
Bill

using System;
using System.IO;
using System.IO.Compression;
using System.Globalization;

namespace FileCopier
{
sealed public class FileCopierMain
{
public enum CompressionAction { Nothing, Compress, Decompress
};

static bool ignoreBinAndObjFolders;
static string compressSuffix = ".BWZIP";
static string fromFolder;
static string toFolder;
static CompressionAction myCompressionAction =
CompressionAction.Nothing;

private FileCopierMain() { }

static void Main(string[] args)
{
//EXAMPLE COMMAND LINE FOR BACKUP AND COMPRESS:
//FileCopier.exe C:\Dev C:\Backups 1 1
//EXAMPLE COMMAND LINE FOR DECOMPRESS AND RESTORE
//FileCopier.exe C:\Backups\Dev_31Jul05 C:\Backups 2 1

if (args.Length != 4)
throw new ArgumentException("Wrong Number of
Arguments");

fromFolder = args[0].Trim(); //The From Folder
toFolder = args[1].Trim(); //The To Folder
if (args[2].Trim() == "1") //SWITCH: 1 = Compress,
2 = Decompress, Else Leave As Is
myCompressionAction = CompressionAction.Compress;
else if (args[2].Trim() == "2")
myCompressionAction = CompressionAction.Decompress;
if (args[3].Trim() == "1") //SWITCH: 1 = Do not
copy folders called BIN or OBJ, Else Copy Everthing
ignoreBinAndObjFolders = true;
else
ignoreBinAndObjFolders = false;

//Eliminate Last Back slash as it screws up logic
if (fromFolder[fromFolder.Length - 1] ==
Path.DirectorySeparatorChar)
fromFolder = fromFolder.Substring(0, fromFolder.Length
- 1);
if (toFolder[toFolder.Length - 1] ==
Path.DirectorySeparatorChar)
toFolder = toFolder.Substring(0, toFolder.Length - 1);

//Work out the folder which we are going to copy to. Do
not overwrite folders
int LastBackSlashPos =
fromFolder.LastIndexOf(Path.DirectorySeparatorChar );
string NewFolderName =
fromFolder.Substring(LastBackSlashPos + 1, fromFolder.Length -
LastBackSlashPos - 1);
NewFolderName += "_" +
System.DateTime.Now.Date.ToString("ddMMMyy",
CultureInfo.CurrentCulture);
if (Directory.Exists(toFolder + Path.DirectorySeparatorChar
+ NewFolderName))
{
int newFolderAppend = 1;
while (Directory.Exists(toFolder +
Path.DirectorySeparatorChar + NewFolderName + "_" +
newFolderAppend.ToString(CultureInfo.CurrentCultur e)))
{
newFolderAppend++;
}
NewFolderName += "_" +
newFolderAppend.ToString(CultureInfo.CurrentCultur e);
}

//Do the copy
CopyDirectory(fromFolder, toFolder +
Path.DirectorySeparatorChar + NewFolderName, true);
}

public static void CopyDirectory(string sourcePath, string
destinationPath, bool recurse)
{
String[] files;

//Ensure that last character is a path separator
if (destinationPath[destinationPath.Length - 1] !=
Path.DirectorySeparatorChar)
destinationPath += Path.DirectorySeparatorChar;

//If need to ignore Bin and Obj then do so
if (ignoreBinAndObjFolders)
{
int secondLastSlashPos = destinationPath.Substring(0,
destinationPath.Length - 1).LastIndexOf(Path.DirectorySeparatorChar);
string lastFolderName =
destinationPath.Substring(secondLastSlashPos + 1,
destinationPath.Length - secondLastSlashPos - 2);
if (lastFolderName.ToUpper(CultureInfo.CurrentCulture )
== "BIN" || lastFolderName.ToUpper(CultureInfo.CurrentCulture) ==
"OBJ")
return;
}

//OK, lets do it
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
files = Directory.GetFileSystemEntries(sourcePath);
foreach (string element in files)
{
if (recurse)
{
// copy sub directories (recursively)
if (Directory.Exists(element))
CopyDirectory(element, destinationPath +
Path.GetFileName(element), recurse);
// copy files in directory
else
{
if (myCompressionAction ==
CompressionAction.Compress)

BWCompressionUtility.CopyAndCompressFile(element, destinationPath +
Path.GetFileName(element) + compressSuffix);
else if (myCompressionAction ==
CompressionAction.Decompress)

BWCompressionUtility.CopyAndDecompressFile(element , destinationPath +
Path.GetFileName(element).Replace(compressSuffix,s tring.Empty));
else
File.Copy(element, destinationPath +
Path.GetFileName(element), true);
}
}
else
{
// only copy files in directory
if (!Directory.Exists(element))
{
if (myCompressionAction ==
CompressionAction.Compress)

BWCompressionUtility.CopyAndCompressFile(element, destinationPath +
Path.GetFileName(element) + compressSuffix);
else if (myCompressionAction ==
CompressionAction.Decompress)

BWCompressionUtility.CopyAndDecompressFile(element , destinationPath +
Path.GetFileName(element).Replace(compressSuffix, string.Empty));
else
File.Copy(element, destinationPath +
Path.GetFileName(element), true);
}
}
}
}
}
sealed public class BWCompressionUtility
{

//References
//http://www.codeguru.com/columns/DotNet/article.php/c9931

//http://groups.google.com.au/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/53ec661446a637a9/bb15f1069eb8e175?lnk=st&q=System.IO.Compression+Fo lder&rnum=1&hl=en#bb15f1069eb8e175
//http://msdn2.microsoft.com/library/as1ff51s(en-us,vs.80).aspx

private BWCompressionUtility() { }

public static void CopyAndCompressFile(string sourceFullPath,
string destinationFullPath)
{
FileStream fsREAD = null;
FileStream fsWRITE = null;
GZipStream compressedZipStream = null;

// Open the file streams
fsREAD = new FileStream(sourceFullPath, FileMode.Open,
FileAccess.Read, FileShare.Read);
fsWRITE = new FileStream(destinationFullPath,
FileMode.Create);

//Create Zip Stream
compressedZipStream = new GZipStream(fsWRITE,
CompressionMode.Compress, true);

//Create buffer
int bytesRead = 0;
long TotalBytesRead = 0;
byte[] buffer = new byte[1000];

//Now transfer the data
while ((bytesRead = fsREAD.Read(buffer,0,buffer.Length)) >
0)
{
compressedZipStream.Write(buffer, 0, bytesRead);
TotalBytesRead += bytesRead;
}

if (TotalBytesRead != fsREAD.Length)
throw new IOException("Unable to read data from file");

//Close all streams. Close zip stream first so it flushes
compressedZipStream.Close();
fsWRITE.Close();
fsREAD.Close();
}
public static void CopyAndDecompressFile(string sourceFullPath,
string destinationFullPath)
{
FileStream fsREAD = null;
FileStream fsWRITE = null;
GZipStream compressedZipStream = null;

// Open the file streams
fsREAD = new FileStream(sourceFullPath, FileMode.Open,
FileAccess.Read, FileShare.Read);
//System.IO.File.OpenRead(sourceFullPath);
fsWRITE = new FileStream(destinationFullPath,
FileMode.Create);

//Create Zip Stream
compressedZipStream = new GZipStream(fsREAD,
CompressionMode.Decompress);

//Create buffer
int bytesRead = 0;
byte[] buffer = new byte[1000];

//Now transfer the data
while ((bytesRead = compressedZipStream.Read(buffer, 0,
buffer.Length)) > 0)
fsWRITE.Write(buffer, 0, bytesRead);

//Close all streams. Close zip stream first so it flushes
compressedZipStream.Close();
fsWRITE.Close();
fsREAD.Close();
}
}
}

Nov 17 '05 #3
or*******@yahoo.com.au wrote:
Here is the latest implementation. Btw - I arbitrarily chose an array
size of 1,000 .. I have not had time to experiment with different array
sizes yet.


I guess you should see a performance gain for large file sizes if you
have a buffer size that's in some relation to your file system's cluster
size. I think (but I'm not quite sure where I got that from) that a
"default" cluster size on NTFS these days is 4KB, so I'd expect best
results for your algorithm when running with a 4096 bytes buffer, or a
multiple thereof.

Oliver Sturm
--
omnibus ex nihilo ducendis sufficit unum
Spaces inserted to prevent google email destruction:
MSN oliver @ sturmnet.org Jabber sturm @ amessage.de
ICQ 27142619 http://www.sturmnet.org/blog
Nov 17 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Jim Hubbard | last post by:
I went to the compression newsgroups, but all I saw was spam. So, I thought I'd post his question here to get the best info I could from other programmers. Which compression algorithm offers...
1
by: Maurice Mertens | last post by:
Hello, I'm having troubles with saving a tiff-file with a certain compression and colordepth. This is the code I use: ----------------------------------------------------------------------...
8
by: Anurag | last post by:
Hi, I am told that Oracle has this "data compression" feature that allows you to store online data ina compressed format. This is different from archived data - you compress only that data which...
2
by: deko | last post by:
Is it best practice to set Unicode Compression to "No" for memo fields in a table? What about text fields? According to the VB help entry: "Data in a Memo field is not compressed unless it...
17
by: dunric | last post by:
After writing the computing urban legend "The Helsinki Code", I spent several nights thinking up how in the world Gustav Larsson, the Finnish PDP-8 computer programmer, could have managed to...
1
by: chris.atlee | last post by:
I'm writing a program in python that creates tar files of a certain maximum size (to fit onto CD/DVD). One of the problems I'm running into is that when using compression, it's pretty much...
3
by: Benny Ng | last post by:
Dear All, Now I met some performance problems in my application. Because according to our business. The size of some web forms are larger than 1xxx MB. So it takes a long time for user opening a...
20
by: chance | last post by:
Hello, I want to add compression to a memory stream and save it in an Oracle database. This is the code I have so far: //save the Word document to a binary field, MemoryStream dataStream = new...
21
by: =?Utf-8?B?VkJB?= | last post by:
I compressed a file with GZipStream class and is larger than the original file.... how can this be?, the original file is 737 KB and the "compressed" file is 1.1 MB. Did i miss something or is...
3
by: GiJeet | last post by:
Hello, we have an app that scans documents into TIFF format and we need to transfer them over the internet. If anyone knows of a SDK we can use that can compress TIFFs on the fly or even if it can...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.