Click here to Skip to main content
15,891,136 members
Articles / Desktop Programming / Windows Forms

Listing and Working with Files in Archives

Rate me:
Please Sign up or sign in to vote.
2.86/5 (6 votes)
22 Jun 2007CPOL 32.3K   529   23  
This article describes how to use CAKE3, which is a wrapper component for many archiver DLLs,
/*
 * Created by SharpDevelop.
 * User: LYCJ
 * Date: 18/12/2006
 * Time: 0:10
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System.IO;
using System;
using System.Collections;
using System.Diagnostics;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using Cake3;

namespace Cake3.SharpZipLib
{
	public class FileSource : IStaticDataSource
	{
		Stream fileStream;
			
		public Stream GetSource()
		{
			return fileStream;
		}
		
		public FileSource(string filename)
		{
			StreamReader sr = new StreamReader(filename);
			sr.ReadToEnd();
			fileStream = sr.BaseStream;
		}			
	}
	
	
	/// <summary>
	/// Description of ZipBase.
	/// </summary>
	public class ZipBase : ArchiverBase
	{
		ICSharpCode.SharpZipLib.Zip.ZipFile ZipDir;
		CakArchiver arc;
		FastZipEvents fze;
		ExtractOptions extrOptions;
		
		public ZipBase(CakArchiver anArc)
		{
			arc = anArc;
			fze = new FastZipEvents();
			fze.ProcessFile += new ProcessFileDelegate(FastZipProcessFile);	
			fze.FileFailure += new FileFailureDelegate(FastZipFileFailure);			
		}
		
		public override bool Open()
		{	
			try
			{								
				ZipDir = new ZipFile(archiveName);					
			}
			catch
			{
				return false;
			}
						
			return true;
		}
		
		public override bool Close()
		{
			try
			{
				ZipDir.Close();
				ZipDir = null;	
			}
			catch
			{
				return false;
			}
			
			
			return true;
		}
		
		public override bool List(string mask)
		{
			if(arc.OnItemList == null) return false;	
			if (ZipDir == null)	return false;					
			
			try
			{
				foreach (ZipEntry e in ZipDir)
				{
					if ((!e.IsDirectory) &&(Utils.MatchMask(e.Name, mask)))
						arc.OnItemList(arc, new ItemListEventArgs(arc,
						                                          new ContentType((UInt32)e.Size, (UInt32)e.CompressedSize,
						                                                          e.DateTime, e.Crc, ModifySlashToCak(e.Name), e.IsCrypted)));
				}
			}
			catch
			{
				return false;
			}
			
			return true;
		}
		
		public void FastZipProcessFile(object sender, ScanEventArgs e)
		{
			arc.DispMessage(Defines.ErrorMessage("PROCESS"), ModifySlashToCak(e.Name));
			e.ContinueRunning = true; 
		}
		
		public void FastZipFileFailure(object sender, ScanFailureEventArgs e)
		{
			arc.DispMessage(Defines.ErrorMessage("PROCESSFAIL"), ModifySlashToCak(e.Name));
			e.ContinueRunning = false; 
		}
				
		internal void ProcessFileDelegate(object sender, ScanEventArgs e)
		{
			
		}

		
		internal bool FastZipConfirmOverwrite(string fileName)
		{
			if (extrOptions.allowOverwrite)
				return true;
			
			OverwriteEventArgs e = new OverwriteEventArgs(arc, fileName);
			if (arc.OnOverwrite != null)
				arc.OnOverwrite(arc, ref e);
			return e.Overwrite;
		}

		
		public override bool Extract(ExtractOptions options)
		{
			try
			{
				FastZip fz = new FastZip(fze);
				fz.Password = options.password;
				extrOptions = options;
				
				foreach (string item in options.extractItem)
					fz.ExtractZip(archiveName, options.extractFolder, FastZip.Overwrite.Prompt , FastZipConfirmOverwrite,
					              ModifySlashFromCak(item), "", true);
				
			}
			catch
			{
				return false;
			}
			return true;
		}
		
		
		private string getRelativePath(string filePath, string basePath)
		{
			if (basePath == "")
				return ZipEntry.CleanName(filePath);
			
			string retVal;
			basePath = Utils.RemoveSlash(basePath).ToLower();			
			string path = Utils.ExtractFilePath(filePath);
			string name = Utils.ExtractFileName(filePath);
			
			if (path.ToLower().IndexOf(basePath) == 0)
				retVal = path.Substring(basePath.Length);
			else retVal = path;
			
			if (retVal != "")
				retVal += @"\";
			
			return ZipEntry.CleanName(retVal + name);
		}
		
		private Hashtable parseAddFile(AddOptions options)
		{
			//TODO: Support mask	
			
			Hashtable retVal = new Hashtable();
			foreach (string item in AddOptions.ParseAddFile(options.addFile, true))
			{
//				Console.WriteLine(item);
				switch (options.addFolder)
				{
					case AddOptions.folderMode.full: //06-16-07 Fixed Zip Add Error my remove front slash.
						retVal.Add(item, ZipEntry.CleanName(item));	
						break;
					case AddOptions.folderMode.relative:
						retVal.Add(item, getRelativePath(item, options.baseFolder));	
						break;
					default:
						retVal.Add(item, Utils.ExtractFileName(item));
						break;
				}
			}									
					
			return retVal;			
		}
			
		public override bool Add(AddOptions options)
		{					

//			Close();
			string tempArchive = options.archiveName+".temp.add";
			Utils.RemoveFile(tempArchive);
			ZipOutputStream output = new ZipOutputStream(File.Create(tempArchive));
			output.SetLevel(options.addCompressLevel);
			
			try
			{
				Hashtable addList = parseAddFile(options);												
																
				byte[] buffer = new byte[1024*16];
				//TODO: Zip Add does not work with archive created by other archiver.
				#region Append existing data									
				if (Utils.FileExists(options.archiveName))
				{
					ZipInputStream input = new ZipInputStream(File.Open(options.archiveName, FileMode.Open));					
					ZipEntry entry = input.GetNextEntry();				
					
					while (entry != null)
					{
						if (!addList.ContainsValue(entry.Name))
						{
//							entry.Size = input.Length;	

							ZipEntry newEntry = new ZipEntry(entry.Name);
							newEntry.Comment = entry.Comment;
							newEntry.CompressionMethod = entry.CompressionMethod;
							newEntry.DateTime = entry.DateTime;
							newEntry.Flags = entry.Flags;							
							
							
							output.PutNextEntry(newEntry);
							int sourceBytes;
							int totalBytes = 0;
							do
							{
								sourceBytes = input.Read(buffer, 0, buffer.Length);
								output.Write(buffer, 0, sourceBytes);
								totalBytes += sourceBytes;
							} while (sourceBytes > 0);	
							
						}
						entry = input.GetNextEntry();
					}
					input.Close();
				}
				
				#endregion
				
				#region Compress new data				
				
				
				foreach (string item in addList.Keys)				
				{					
//					Debug.WriteLine(addList[item]);
					ZipEntry entry = new ZipEntry((string)addList[item]);
					entry.DateTime = DateTime.Now;					
//					entry.Size = Utils.GetFileInfo(item).Length;
					output.PutNextEntry(entry);
					
					FileStream fs = File.OpenRead(item);
					int sourceBytes;

					do
					{
						sourceBytes = fs.Read(buffer, 0, buffer.Length);
						output.Write(buffer, 0, sourceBytes);
					} while (sourceBytes > 0);
					
					fs.Close(); //06-16-07 Fix file locked after file add.
					fs.Dispose();
				}
				#endregion
				
				output.Finish();
				output.Close();	
				
				Utils.MoveFile(tempArchive, options.archiveName);
								
				
			}					
			catch (Exception ex)
			{
				output.Close();	
				Open();
				Debug.WriteLine(ex.Message);
				arc.DispError(ex.Message, options.archiveName);
				return false;
			}
			finally
			{
				
//				Open();
			}
			return true;
		}
		
		bool matchMasks(ArrayList deleteFileMasks, string fileName)
		{
			foreach (string mask in deleteFileMasks)
				if (Utils.MatchMask(fileName, mask))
				    return true;
			return false;
		}
		
		public override bool Delete(DeleteOptions options)
		{
//			Close();
			try			
			{
				string tempArchive = options.archiveName+".temp.del";
				Utils.RemoveFile(tempArchive);
				ZipOutputStream output = new ZipOutputStream(File.Create(tempArchive));				
				byte[] buffer = new byte[4096];
				
				ArrayList fileList = new ArrayList();
				foreach (string item in options.deleteFile)
					fileList.Add(this.ModifySlashFromCak(item.ToLower()));				
				foreach (string item in fileList)	
					Debug.WriteLine(item);
				
				#region Add files to temp archive.
				if (Utils.FileExists(options.archiveName))
				{					
					ZipInputStream input = new ZipInputStream(File.Open(options.archiveName, FileMode.Open));
					ZipEntry entry = input.GetNextEntry();
					while (entry != null)
					{
						
						ZipEntry newEntry = new ZipEntry(entry.Name);
						newEntry.Comment = entry.Comment;
						newEntry.CompressionMethod = entry.CompressionMethod;
						newEntry.DateTime = entry.DateTime;
						newEntry.Flags = entry.Flags;	
						
						string entryFile = Utils.RemoveFrontSlash(newEntry.Name.ToLower());
						//if (!fileList.Contains(entryFile))
						if (!matchMasks(fileList, entryFile))
						{							
							output.PutNextEntry(newEntry);
							int sourceBytes;
							do
							{
								sourceBytes = input.Read(buffer, 0, buffer.Length);
								output.Write(buffer, 0, sourceBytes);
							} while (sourceBytes > 0);
						}
						entry = input.GetNextEntry();
					}
					input.Close();
				}
				#endregion
				
				output.Finish();
				output.Close();				
								
				Utils.MoveFile(tempArchive, options.archiveName);
			}
			catch
			{
				return false;
			}
			finally
			{
//				Open();
			}
			return true;
		}
		
		public override bool Test()
		{
			bool retVal = false;
			
			try
			{
				if (Open())
				{					
					retVal = ZipDir.TestArchive(true);
					Close();
				}
			}
			catch
			{
				return false;
			}
			
			return retVal;
		}
		
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder
Hong Kong Hong Kong

Comments and Discussions