首先,應用ICSharpCode.SharpZipLib.dll,這是個開源軟件,網絡上可以下到源代碼。
注意,這個開源軟件的084版本或以上提供一個方法直接壓縮與解壓文件夾。方法很簡單,隻要如下幾行代碼就可以了:
private void Button3_Click(object sender, System.EventArgs e)
{
ICSharpCode.SharpZipLib.Zip.FastZip tt=new FastZip();
tt.CreateZip("c://zip//driver1.zip","c://driver//",true,"");
tt.ExtractZip("c://zip//driver1.zip","c://unzipped//","");
}
但是,這樣做就喪失了靈活性,據實測,壓縮的文件好像比自己寫要稍微大一些,估計是沒有辦法指定壓縮等級的原因;而且,我看了下源代碼,好像也沒有看到CRC校驗。
要改進以上不足,我們可以自己寫兩個類,來分別完成壓縮與解壓,代碼如下:
壓縮類:
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
namespace IISTest.Compression
{
public class ZipClass
{
Crc32 crc = new Crc32();
public void ZipFile(string FileToZip, string ZipedFile ,int CompressionLevel, int BlockSize)
{
//如果檔沒有找到,則報錯
if (! System.IO.File.Exists(FileToZip))
{
throw new System.IO.FileNotFoundException("The specified file " + FileToZip + " could not be found. Zipping aborderd");
}
System.IO.FileStream StreamToZip = new System.IO.FileStream(FileToZip,System.IO.FileMode.Open , System.IO.FileAccess.Read);
System.IO.FileStream ZipFile = System.IO.File.Create(ZipedFile);
ZipOutputStream ZipStream = new ZipOutputStream(ZipFile);
ZipEntry ZipEntry = new ZipEntry("ZippedFile");
ZipStream.PutNextEntry(ZipEntry);
ZipStream.SetLevel(CompressionLevel);
byte[] buffer = new byte[BlockSize];
System.Int32 size =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,size);
try
{
while (size < StreamToZip.Length)
{
int sizeRead =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,sizeRead);
size += sizeRead;
}
}
catch(System.Exception ex)
{
throw ex;
}
ZipStream.Finish();
ZipStream.Close();
StreamToZip.Close();
}
private string AddZip( string fileName, string zipName,ZipOutputStream s)
{
try
{
FileStream fs = File.OpenRead( fileName );
byte[] buffer = new byte[fs.Length];
fs.Read( buffer, 0, buffer.Length );
fileName = Path.GetFileName( fileName );
long fileLength = fs.Length;
fs.Close();
ZipEntry entry = new ZipEntry( zipName );
entry.DateTime = DateTime.Now;
entry.Size = fileLength;
crc.Reset();
crc.Update( buffer );
entry.Crc = crc.Value;
s.PutNextEntry( entry );
s.Write( buffer, 0, buffer.Length );
return string.Empty;
}
catch( Exception addEx )
{
return addEx.ToString();
}
}
private void AddFolder(string folderName,string zipName,ZipOutputStream s)
{
if( Directory.Exists( folderName ) )
{
foreach( string str in Directory.GetFileSystemEntries( folderName ) )
{
if( File.Exists( str ) )
AddZip( str, zipName + "//" + str.Substring( str.LastIndexOf( "//" ) + 1 ),s );
else
AddFolder( str, zipName + "//" + str.Substring( str.LastIndexOf( "//" ) + 1 ),s );
}
}
}
public void ZipFileMain(string[] args)
{
string dirName=null;
dirName = Path.GetDirectoryName(Path.GetFullPath(args[1]));
if(!Directory.Exists(dirName))
{
Directory.CreateDirectory(dirName);
}
ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));
s.SetLevel(6); // 0 - store only to 9 - means best compression
AddFolder(args[0],args[0].Substring(args[0].Length-1)=="//"?args[0].Substring(0,args[0].Length-1).Substring(args[0].Substring(0,args[0].Length-1).LastIndexOf("//")+1):args[0].Substring(args[0].LastIndexOf("//")+1),s);
s.Finish();
s.Close();
}
}
}
解壓類:
using System;
using System.Text;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
namespace IISTest.DeCompression
{
public class UnZipClass
{
private string targetDirectory="";
ZipInputStream s;
public void UnZip(string[] args,string password)
{
s = new ZipInputStream(File.OpenRead(args[0]));
try
{
if (password != null)
{
s.Password = password;
}
this.targetDirectory = args[1].ToString();
ZipEntry entry;
while ( (entry = s.GetNextEntry()) != null )
{
ExtractEntry(entry);
}
}
finally
{
s.Close();
}
}
private void ExtractEntry(ZipEntry entry)
{
bool doExtraction =true;
string dirName = null;
string targetName = null;
if ( doExtraction )
{
string entryFileName;
if (Path.IsPathRooted(entry.Name))
{
string workName = Path.GetPathRoot(entry.Name);
workName = entry.Name.Substring(workName.Length);
entryFileName = Path.Combine(Path.GetDirectoryName(workName), Path.GetFileName(entry.Name));
}
else
{
entryFileName = entry.Name;
}
targetName = Path.Combine(targetDirectory, entryFileName);
dirName = Path.GetDirectoryName(Path.GetFullPath(targetName));
doExtraction = doExtraction && (entryFileName.Length > 0);
}
if ( doExtraction && !Directory.Exists(dirName) )
{
if ( !entry.IsDirectory )
{
try
{
Directory.CreateDirectory(dirName);
}
catch
{
doExtraction = false;
}
}
}
if ( doExtraction && entry.IsFile )
{
ExtractFileEntry(entry, targetName);
}
}
private void ExtractFileEntry(ZipEntry entry, string targetName)
{
bool proceed = true;
byte[] buffer = new byte[2048];
if ( proceed )
{
FileStream streamWriter = File.Create(targetName);
try
{
if ( buffer == null )
{
buffer = new byte[2048];
}
int size;
do
{
size = s.Read(buffer, 0, buffer.Length);
streamWriter.Write(buffer, 0, size);
} while (size > 0);
}
finally
{
streamWriter.Close();
}
File.SetLastWriteTime(targetName, entry.DateTime);
}
}
private void UnzipFolder(string zipName,ZipInputStream s)
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
if(theEntry.IsDirectory)
{
// AddFolder( str, zipName + "//" + str.Substring( str.LastIndexOf( "//" ) + 1 ),s );
string directoryNameSub = Path.GetDirectoryName(zipName+"//" + Path.GetFileName(theEntry.Name)+"//");
Directory.CreateDirectory(directoryNameSub);
UnzipFolder(directoryNameSub,s);
}
else
{
string fileName=zipName+"//"+Path.GetFileName(theEntry.Name);
UnzipFile(fileName,s);
}
}
}
private void UnzipFile(string zipName,ZipInputStream s)
{
//解壓檔到指定的目錄
FileStream streamWriter = File.Create(zipName);
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
streamWriter.Close();
}
}
}
完成後,調用的過程如下:
private void Button1_Click(object sender, System.EventArgs e)
{
string []FileProperties=new string[2];
FileProperties[0]="C://driver//";//待壓縮檔目錄
FileProperties[1]="C://zip//driver.zip"; //壓縮後的目標檔
IISTest.Compression.ZipClass Zc=new IISTest.Compression.ZipClass();
Zc.ZipFileMain(FileProperties);
}
private void Button2_Click(object sender, System.EventArgs e)
{
string []FileProperties=new string[2];
FileProperties[0]="C://zip//driver.zip";//待解壓的文件
FileProperties[1]="C://unzipped//";//解壓後放置的目標目錄
IISTest.DeCompression.UnZipClass UnZc=new IISTest.DeCompression.UnZipClass();
UnZc.UnZip(FileProperties,null);
}
這樣的靈活性就大多了,可以自己指定壓縮的等級等屬性。
上面我們引用的哪個DLL全部是用C#寫成的,採用的壓縮方法好像是HUFFMAN編碼【沒怎麼詳細看】,隻能壓縮成ZIP格式,中等壓縮和WINRAR壓縮成ZIP格式的文件大小完全相等,壓縮速度比WINRAR壓縮成RAR格式要快很多。壓縮後的ZIP文件可以被RAR解壓。
唯一的缺點就是不能壓縮成RAR格式,當然了,也不能解壓RAR文件。