c#壓縮解壓縮cab文件
CabDotNet源代碼單文件版,支持cab壓縮解壓縮
壓縮cab文件
using System;
using System.IO;
using System.Runtime.InteropServices;
using CabWrapper;
using CabDotNet;
// Jim Mischel <jim@mischel.com>, 11/21/2004
namespace testfci
{
class Class1
{
// When a CAB file reaches this size, a new CAB will be created
// automatically. This is useful for fitting CAB files onto disks.
//
// If you want to create just one huge CAB file with everything in
// it, change this to a very very large number.
private const int MediaSize = 300000;
// When a folder has this much compressed data inside it,
// automatically flush the folder.
//
// Flushing the folder hurts compression a little bit, but
// helps random access significantly.
private const int FolderThreshold = 900000;
// Compression type to use
private const FciCompression CompressionType = FciCompression.MsZip;
// Our internal state
//
// The FCI APIs allow us to pass back a state pointer of our own
internal class ClientState
{
internal int totalCompressedSize; /* total compressed size so far */
internal int totalUncompressedSize; /* total uncompressed size so far */
}
[STAThread]
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("TESTFCI - Demonstrates how to use the FCI library API calls\n");
Console.WriteLine("Usage: TESTFCI file1 [+] [file2] [+] [file3] ...\n");
Console.WriteLine("Where <file1>...<fileN> are input files, and a + forces a folder boundary)");
Console.WriteLine("Output cabinets are named C:\\TEST1.CAB, C:\\TEST2.CAB, ...\n");
Console.WriteLine(" e.g. testfci test.dat source.c test.c + baloon.bmp cabbage.bmp\n");
return;
}
if (doFciTest(args))
Console.WriteLine(@"TESTFCI was successful, cabinets created on C:\");
else
Console.WriteLine("TESTFCI failed");
}
static bool doFciTest(string[] args)
{
// our client state
ClientState cs = new ClientState();
cs.totalCompressedSize = 0;
cs.totalUncompressedSize = 0;
bool returnResult = true;
CabCompressor cabComp = new CabCompressor();
try
{
setCabParameters(cabComp);
cabComp.UserData = cs;
// setup event handlers
cabComp.NextCabinet += new NextCabinetEventHandler(cabComp_NextCabinet);
cabComp.FilePlaced += new FilePlacedEventHandler(cabComp_FilePlaced);
cabComp.FileAdded += new ProgressEventHandler(cabComp_FileAdded);
cabComp.FolderComplete += new ProgressEventHandler(cabComp_FolderComplete);
cabComp.CabinetComplete += new ProgressEventHandler(cabComp_CabinetComplete);
// add each file
foreach (string filename in args)
{
// Flush the folder?
if (filename == "+")
{
cabComp.FlushFolder();
// continue with next file name
continue;
}
// Don't store path information in the cabinet file
string strippedName = Path.GetFileName(filename);
cabComp.AddFile(filename, strippedName, false, CompressionType);
}
// All done adding files. Flush the cabinet.
// This will automatically flush the folder first.
cabComp.FlushCabinet();
Console.Write(" \r");
}
catch (Exception ex)
{
Console.WriteLine(ex);
returnResult = false;
}
finally
{
cabComp.Dispose();
}
return returnResult;
}
static void setCabParameters(CabCompressor cabComp)
{
cabComp.CabInfo.MaxCabinetSize = MediaSize;
cabComp.CabInfo.MaxFolderSize = FolderThreshold;
// Don't reserve space for any extensions
cabComp.CabInfo.HeaderReserve = 0;
cabComp.CabInfo.FolderReserve = 0;
cabComp.CabInfo.DataReserve = 0;
// We use this to create the cabinet name
cabComp.CabInfo.CabinetNumber = 1;
// If you want to use disk names, use this to count disks
cabComp.CabInfo.DiskNumber = 0;
// Choose your own SetId
cabComp.CabInfo.SetId = 12345;
// Only important if CABs are spanning multiple disks,
// in which case you will want to use a real disk name.
//
// Can be left as an empty string.
cabComp.CabInfo.DiskName = "MyDisk";
// where to store the created CAB files
cabComp.CabInfo.CabPath = @"e:\cabdotnet\trash\";
// store name of first CAB file
cabComp.CabInfo.CabName = storeCabName(cabComp.CabInfo.CabinetNumber);
}
static string storeCabName(int iCab)
{
return string.Format("TEST{0}.CAB", iCab);
}
public static void cabComp_NextCabinet(object sender, NextCabinetEventArgs e)
{
// Cabinet counter has been incremented already by FCI
// Store next cabinet name
string cabName = storeCabName(e.CabInfo.CabinetNumber);
e.CabInfo.CabName = cabName;
// You could change the disk name here too, if you wanted
e.Result = true;
}
public static void cabComp_FilePlaced(object sender, FilePlacedEventArgs e)
{
Console.WriteLine(" placed file '{0}' (size {1}) on cabinet '{2}'",
e.FileName, e.FileSize, e.CabInfo.CabName);
if (e.Continuation)
Console.WriteLine(" (Above file is a later segment of a continued file)");
e.Result = 0;
}
public static void cabComp_FileAdded(object sender, ProgressEventArgs e)
{
ClientState cs = (ClientState)e.UserData;
cs.totalCompressedSize += e.CompressedBlockSize;
cs.totalUncompressedSize += e.UncompressedBlockSize;
Console.Write(
"Compressing: {0} -> {1} \r",
cs.totalUncompressedSize,
cs.totalCompressedSize
);
e.Result = 0;
}
public static void cabComp_FolderComplete(object sender, ProgressEventArgs e)
{
int percentage = GetPercentage(e.FolderBytesCopied, e.FolderSize);
Console.Write("Copying folder to cabinet: {0}% \r", percentage);
e.Result = 0;
}
private static int GetPercentage(int a, int b)
{
if (b == 0)
return 0;
return ((a*100)/b);
}
public static void cabComp_CabinetComplete(object sender, ProgressEventArgs e)
{
Console.Write("Estimated cabinet size = {0}. Actual size = {1}", e.EstimatedCabSize, e.ActualCabSize);
e.Result = 0;
}
}
}
解壓縮cab文件
using System;
using System.IO;
using System.Runtime.InteropServices;
using CabDotNet;
using CabWrapper;
// Jim Mischel <jim@mischel.com>, 11/21/2004
namespace testfdi
{
class Class1
{
private static string destinationDirectory = string.Empty;
[STAThread]
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine(
"TESTFDI - Demonstrates how to use the CabDecompressor interface.\n\n" +
"Usage: TESTFDI cabinet dest_dir\n\n" +
"Where <cabinet> is the name of a cabinet file, and <dest_dir>\n" +
"is the destination for the files extracted\n\n" +
" e.g. testfdi c:\\test1.cab c:\\\n");
return;
}
destinationDirectory = args[1];
if (doFdiTest(args[0]))
Console.WriteLine("TestFdi was successful.");
else
Console.WriteLine("TestFdi failed.");
}
static bool doFdiTest(string cabinetFullPath)
{
using (CabDecompressor decomp = new CabDecompressor())
{
// setup event handlers
decomp.NotifyCabinetInfo += new NotifyEventHandler(decomp_NotifyCabinetInfo);
decomp.NotifyCloseFile += new NotifyEventHandler(decomp_NotifyCloseFile);
decomp.NotifyCopyFile += new NotifyEventHandler(decomp_NotifyCopyFile);
decomp.NotifyEnumerate += new NotifyEventHandler(decomp_NotifyEnumerate);
decomp.NotifyNextCabinet += new NotifyEventHandler(decomp_NotifyNextCabinet);
decomp.NotifyPartialFile += new NotifyEventHandler(decomp_NotifyPartialFile);
FdiCabinetInfo cabInfo = new FdiCabinetInfo();
using (FileStream fs = new FileStream(cabinetFullPath, FileMode.Open))
{
if (!decomp.IsCabinetFile(fs, cabInfo))
{
Console.WriteLine("File is not a cabinet.");
return false;
}
// The file is a cabinet. Display some info.
Console.WriteLine(
"Information on cabinet file '{0}'\n" +
" Total length of cabinet file : {1}\n" +
" Number of folders in cabinet : {2}\n" +
" Number of files in cabinet : {3}\n" +
" Cabinet set ID : {4}\n" +
" Cabinet number in set : {5}\n" +
" RESERVE area in cabinet? : {6}\n" +
" Chained to prev cabinet? : {7}\n" +
" Chained to next cabinet? : {8}\n",
cabinetFullPath,
cabInfo.Length,
cabInfo.FolderCount,
cabInfo.FileCount,
cabInfo.SetId,
cabInfo.CabinetNumber,
cabInfo.HasReserve,
cabInfo.HasPrev,
cabInfo.HasNext);
}
// extract path and filename
string cabinetName = Path.GetFileName(cabinetFullPath);
string cabinetPath = Path.GetDirectoryName(cabinetFullPath);
if (cabinetPath != string.Empty)
cabinetPath = cabinetPath + Path.DirectorySeparatorChar;
// let's copy some files!
if (!decomp.ExtractFiles(cabinetFullPath))
{
Console.WriteLine("FdiCopy failed. Error code {0}", decomp.ErrorInfo.FdiErrorCode);
return false;
}
return true;
}
}
public static void decomp_NotifyCabinetInfo(object sender, NotifyEventArgs e)
{
Console.WriteLine("Cabinet Info" +
" Next cabinet = {0}\n" +
" Next disk = {1}\n" +
" Cabinet path = {2}\n" +
" Cabinet set id = {3}\n" +
" Cabinet # in set = {4}",
e.args.str1, e.args.str2, e.args.CabinetPathName,
e.args.SetId, e.args.CabinetNumber);
e.Result = 0;
}
public static void decomp_NotifyPartialFile(object sender, NotifyEventArgs e)
{
Console.WriteLine("Partial File\n" +
" Name of continued file = {0}\n" +
" Name of cabinet where file starts = {1}\n" +
" Name of disk where file starts = {2}",
e.args.str1, e.args.str2, e.args.CabinetPathName);
e.Result = 0;
}
public static void decomp_NotifyCopyFile(object sender, NotifyEventArgs e)
{
Console.Write("Copy File\n" +
" File name in cabinet = {0}\n" +
" Uncompressed file size = {1}\n" +
" Copy this file? (y/n): ",
e.args.str1, e.args.Size);
string response = "Y";
do
{
response = Console.ReadLine().ToUpper();
} while (response != "Y" && response != "N");
if (response == "Y")
{
int err = 0;
string destFilename = destinationDirectory + e.args.str1;
IntPtr fHandle = CabIO.FileOpen(destFilename, FileAccess.Write,
FileShare.ReadWrite, FileMode.Create, ref err);
e.Result = (int)fHandle;
}
else
{
e.Result = 0;
}
}
public static void decomp_NotifyCloseFile(object sender, NotifyEventArgs e)
{
Console.WriteLine("Close File Info\n" +
" File name in cabinet = {0}", e.args.str1);
string fname = destinationDirectory + e.args.str1;
// TODO: Most of this function probably should be encapsulated in the parent object.
int err = 0;
CabIO.FileClose(e.args.FileHandle, ref err, null);
// set file date and time
DateTime fileDateTime = FCntl.DateTimeFromDosDateTime(e.args.FileDate, e.args.FileTime);
File.SetCreationTime(fname, fileDateTime);
File.SetLastWriteTime(fname, fileDateTime);
// get relevant file attributes and set attributes on the file
FileAttributes fa = FCntl.FileAttributesFromFAttrs(e.args.FileAttributes);
File.SetAttributes(fname, fa);
e.Result = 1;
}
public static void decomp_NotifyNextCabinet(object sender, NotifyEventArgs e)
{
Console.WriteLine("Next Cabinet\n" +
" Name of next cabinet where file continued = {0}\n" +
" Name of next disk where file continued = {1}\n" +
" Cabinet path name = {2}\n",
e.args.str1, e.args.str2, e.args.str3);
e.Result = 0;
}
public static void decomp_NotifyEnumerate(object sender, NotifyEventArgs e)
{
}
}
}
本文由用戶 KirSNVD 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!