HTTP在線壓縮與解壓

来源:互联网 发布:软件数据彻底清除 编辑:程序博客网 时间:2024/05/22 09:41

首先,應用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文件。