|
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace QiHe.CodeLib.Compress
{
/// <summary>
/// zip archive file.
/// Multi disk, encryption and Zip64 are not supported.
/// </summary>
public class ZipArchive
{
public string ZipFile;
public Dictionary<string, ZipEntry> Entries = new Dictionary<string, ZipEntry>();
public ZipArchive() { }
bool isDifferentialArchive = false;
DateTime BaseDateTime = DateTime.MinValue;
public ZipArchive(DateTime baseDateTime)
{
isDifferentialArchive = true;
BaseDateTime = baseDateTime;
}
public IEnumerable<string> Files
{
get { return Entries.Keys; }
}
/// <summary>
/// file comment length
/// </summary>
UInt16 FileCommentLength = 0;
byte[] FileCommentBytes;
public string Comment
{
get
{
return ZipFormat.TextEncoding.GetString(FileCommentBytes);
}
set
{
FileCommentBytes = ZipFormat.TextEncoding.GetBytes(value);
FileCommentLength = (UInt16)FileCommentBytes.Length;
}
}
public void Add(string basePath, string relativePath)
{
ZipEntry zipEntry = new ZipEntry();
zipEntry.FilePath = Path.Combine(basePath, relativePath);
zipEntry.FileName = relativePath;
if (File.Exists(zipEntry.FilePath))
{
zipEntry.ModifiedTime = File.GetLastWriteTime(zipEntry.FilePath);
zipEntry.CompressMethod = (ushort)CompressionMethod.Deflate;
if (isDifferentialArchive && zipEntry.ModifiedTime <= BaseDateTime)
{
return;
}
}
else if (Directory.Exists(zipEntry.FilePath))
{
zipEntry.ModifiedTime = Directory.GetLastWriteTime(zipEntry.FilePath);
zipEntry.IsFile = false;
}
else
{
//throw new FileNotFoundException(zipEntry.FilePath);
return; //skip
}
Entries[zipEntry.FileName] = zipEntry;
}
public void Save(string destfile)
{
using (FileStream output = File.Create(destfile))
{
WriteLocalFiles(output);
BinaryWriter writer = new BinaryWriter(output);
WriteCentralDirectory(writer);
WriteCentralDirectoryEnd(writer);
writer.Flush();
}
}
public static ZipArchive Load(string zipfile)
{
ZipArchive archive = new ZipArchive();
archive.ZipFile = zipfile;
using (FileStream input = File.OpenRead(zipfile))
{
BinaryReader reader = new BinaryReader(input);
while (true)
{
try
{
ZipEntry zipEntry = new ZipEntry();
zipEntry.ReadLocalHeader(reader);
archive.Entries[zipEntry.FileName] = zipEntry;
reader.BaseStream.Position += zipEntry.CompressedSize;
}
catch
{
break;
}
}
}
return archive;
}
public void Extract(string file, string destdir)
{
using (FileStream input = File.OpenRead(ZipFile))
{
string destfile = Path.Combine(destdir, file);
ZipEntry entry = Entries[file];
entry.FilePath = destfile;
entry.IsFile = !destfile.EndsWith("/");
entry.Decompress(input);
}
}
private void WriteLocalFiles(FileStream output)
{
foreach (ZipEntry entry in Entries.Values)
{
entry.Compress(output);
}
}
private void WriteDigitalSignature(BinaryWriter writer)
{
writer.Write(ZipFormat.SignatureHeaderSignature);
//to be implemented
}
long CentralDirectoryOffset;
long CentralDirectorySize;
private void WriteCentralDirectory(BinaryWriter writer)
{
CentralDirectoryOffset = writer.BaseStream.Position;
foreach (ZipEntry entry in Entries.Values)
{
entry.WriteCentralHeader(writer);
}
//WriteDigitalSignature(writer);
CentralDirectorySize = writer.BaseStream.Position - CentralDirectoryOffset;
}
private void WriteCentralDirectoryEnd(BinaryWriter writer)
{
writer.Write(ZipFormat.CentralDirectorySignature);
writer.Write((UInt16)0); //number of this disk
writer.Write((UInt16)0); //number of the disk with the start of the central directory
writer.Write((UInt16)Entries.Count); //total number of entries in the central directory on this disk
writer.Write((UInt16)Entries.Count); //total number of entries in the central directory
writer.Write((UInt32)CentralDirectorySize); //size of the central directory
writer.Write((UInt32)CentralDirectoryOffset); //offset of start of central directory with respect to the starting disk number
writer.Write((UInt16)FileCommentLength); //.ZIP file comment length
if (FileCommentLength > 0)
{
writer.Write(FileCommentBytes); //.ZIP file comment
}
}
}
}
|
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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.