Abstract
I was seeking a program for backing up my files in a differential way: being able to store the files modified since last back-up. To do so, there is a good way: to use the last-modified date of the file. I wanted as well to record them in a widely spread format to have a good chance of being able to restore them within several years.
The zip format seems to be the best one for this purpose. And I wanted the process to be completely automatic in order to avoid losing time and potentially make mistakes while saving the files. To that end, a good old batch file seemed to be the best. So the problem was finding a zip command line utility able to do that.
Only one free program like this seems to exist on the internet: the open source Info-ZIP utility. But there is a code page issue with Info-Zip, which makes zip files produced by InfoZip completely readable by some zippers, but not all, when the file names contain extended characters like those used by some European languages. For example, the Windows built-in zip functionality displays wrong file names if these names contain extended characters and if the zip file was created with Info-Zip. It's not important if the file names contain only US standard characters, but if, for example, they contain specific European characters, such as ń, �, �, etc... it's not very convenient.
With no other utility being available, I decided to write one myself. Several zip libraries are available on the net. I decided to use the ic#code one. It worked relatively simply.
I made this program available for the CodeProject community as a complete sample program using this library. I hope that it could be helpful to readers wanting to add add a zip functionality to their software, or simply to use the utility for their own backup purpose.
Background
Several other CodeProject articles talk about the ic#code zip library, like this one which gives a basic view about the way to zip and unzip files.
Using the Utility
The utility can be used as a conventional zip utility, but it has a special feature to easily and automatically create a differential backup file. When started with the conventional /? parameter, it displays its help text :
MZip
Zip archive creating and updating utility.
Syntax:
MZip /zip=Zip file name [/a] [/d=date or file name] [/r|R] [/l] file(s) or
directory(ies) name(s)
/zip=Name of the file to create or update
/a if present and if the zip file exists, its contents is merged with
the new files otherwise, a new zip file is created.
/d=date/time The files are stored to the zip archive if they were modified
after this date/time.
A file name can be given instead of a date. In this case the date/time when
the file was last modified is used as a starting date for storing files.
If a date/time is given, its format depends on the language settings of
the computer and can be any usual format for a date/time such as 1/1/2000 8:00.
If a date such as 10:30 is given it means today at 10:30.
[/l] tells the program only to list the files, not to store them.
/r means to store the relative directory of the files when a directory name
is given, and the absolute path name when a file name is given.
/R means to store the absolute path of the files in any case.
This program is provided on an "AS-IS" basis. You can use it freely but
at your own risks. The author is not liable for any direct
or indirect damage caused by the program.
What is specific is the /d=
optional parameter. This parameter can contain either a date/time string or a file name. If it contains a date, it means that the program must record files in the selection, modified after this date. If it contains a file name, it means that the program must take this date in the last-modified date of this file. This makes it possible to create a very simple batch file to create a differential bakup:
MZip /zip=DifferentialBackup.zip /d=MyTimeStamp.txt /R c:\MyDirectory
echo My time stamp >MyTimeStamp.txt
Such a batch file will create an archive containing the files modified since the last time it was started.
A slightly more complex and more interesting batch would be:
date /t >%temp%\MyDate.txt
set /p MyDate= <%temp%\MyDate.txt
set MyDate=%MyDate: =%
set MyDate=%MyDate:/=.%
if exist %temp%\MyDate.txt del %temp%\MyDate.txt
MZip /zip=Backup.%MyDate%.zip /d=MyTimeStamp.txt /R c:\MyDirectory
echo My time stamp >MyTimeStamp.txt
This batch file gives a name depending on the date to the backup file. You can, for example, burn the resulting file directly to a CD or a DVD to make an efficient backup, and do it each week: each weekly file will have a different name.
In case of disaster, the files can be recovered by unzipping them in chronological order.
Because MZip creates zip files compatible with the Windows zip feature, it's also a good choice when you need to zip files from the command line (mainly if your language uses an extended character set).
Using the Code
The major part of the code aims to make a list of the files to compress and to store it to a SortedList
collection.
One thing is interesting here: the AnalyseCommande
class, which is a reusable class parsing the command line in a relatively flexible way.
What is also interesting, is the use of the SharpZipLib
library, either for reading or for writing a zip file. To read a file, you first have to create a FileStream
object. Then, from this object to create a ZipInputSream
object, and, to read a file within the archive, to create a ZipEntry
object corresponding to the file you want to read. In this program they are selected sequentially one after each other. Then simply read the data like an ordinary stream, using the Read
method of the ZipInputStream
object. That's all and it's very simple and short as shown in the following part of the program:
FlotEntree=new FileStream(NomFichierZip,FileMode.Open,FileAccess.Read,
FileShare.None);
FichierZipEntree=new ZipInputStream(FlotEntree);
for(MonEntreeLue=FichierZipEntree.GetNextEntry();
MonEntreeLue!=null;MonEntreeLue=FichierZipEntree.GetNextEntry())
{
MonEntree=new ZipEntry(ZipEntry.CleanName(MonEntreeLue.Name));
MonEntree.DateTime=MonEntreeLue.DateTime;
MonEntree.Size=MonEntreeLue.Size;
FichierZipSortie.PutNextEntry(MonEntree);
for(LongueurRestante=(int)FichierZipEntree.Length;LongueurRestante!=0;)
{
LongueurLue=FichierZipEntree.Read(BufferTransfert,0,
LongueurRestante<1024*1024?LongueurRestante:1024*1024);
if(LongueurLue==0)break;
FichierZipSortie.Write(BufferTransfert,0,LongueurLue);
LongueurRestante-=LongueurLue;
}
}
This program is slightly more complex than simply reading the file as it writes the read data to the new zip archive.
Writing to a zip file is as simple, but it uses the ZipOutpuStream
class.
The complete program was created with the SharpDevelop IDE, an interesting open source IDE for .NET, and the sln project works with this IDE. It should work as well with Microsoft's tools. The MZip.exe program is autonomous and does not need any DLL to work. This was made possible by using the Microsoft's ILMerge utility to merge the original exe file (created by the compiler) and the DLL.
Points of Interest
Programming this tool was not very complex. But the SharpZipLib offers a lot of classes, which sometimes look like to be equivalent and it is not completely easy to find his way through all these classes. This program shows an efficient way to read ot create zip files through two main classes, ZipInputStream
and ZipOutputStream
.
My purpose was to help any developer wanting to create zip functionalities. Using this library the way it's done in my program is easy and quick and gives great results.