334 lines
12 KiB
ObjectPascal
334 lines
12 KiB
ObjectPascal
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ****************************************************************************
|
|
// * Project : FWZip
|
|
// * Unit Name : BuildWithException
|
|
// * Purpose : Äåìîíñòðàöèÿ ðàáîòû ñ èñêëþ÷åíèÿìè
|
|
// * : ïðè ñîçäàíèè è ðàñïàêîâêå àðõèâà
|
|
// * Author : Àëåêñàíäð (Rouse_) Áàãåëü
|
|
// * Copyright : © Fangorn Wizards Lab 1998 - 2013.
|
|
// * Version : 1.0.10
|
|
// * Home Page : http://rouse.drkb.ru
|
|
// * Home Blog : http://alexander-bagel.blogspot.ru
|
|
// ****************************************************************************
|
|
// * Stable Release : http://rouse.drkb.ru/components.php#fwzip
|
|
// * Latest Source : https://github.com/AlexanderBagel/FWZip
|
|
// ****************************************************************************
|
|
//
|
|
// Èñïîëüçóåìûå èñòî÷íèêè:
|
|
// ftp://ftp.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip
|
|
// http://zlib.net/zlib-1.2.5.tar.gz
|
|
// http://www.base2ti.com/
|
|
//
|
|
|
|
// Äàííûé ïðèìåð ïîêàçûâàåò ðàáîòó ñ ðàçëè÷íûìè îøèáêàìè ìîãóùèìè âîçíèêíóòü
|
|
// â ïðîöåññå ñîçäàíèÿ è ðàñïàêîâêè àðõèâà, à òàê-æå ñïîñîáû èõ îáðàáîòêè.
|
|
|
|
program BuildWithException;
|
|
|
|
{$APPTYPE CONSOLE}
|
|
|
|
uses
|
|
Windows,
|
|
Classes,
|
|
SysUtils,
|
|
TypInfo,
|
|
FWZipConsts,
|
|
FWZipWriter,
|
|
FWZipReader;
|
|
|
|
var
|
|
Writer: TFWZipWriter;
|
|
Reader: TFWZipReader;
|
|
Method: TMethod;
|
|
hOFStruct: TOFStruct;
|
|
hFile: THandle;
|
|
|
|
//
|
|
// Ïðîöåäóðà âûâîäèò ðåçóëüòàò ðàáîòû ôóíêöèè BuildZip
|
|
// =============================================================================
|
|
procedure ShowBuildResult(Value: TBuildZipResult);
|
|
begin
|
|
Writeln(GetEnumName(TypeInfo(TBuildZipResult), Integer(Value)));
|
|
end;
|
|
|
|
//
|
|
// Ïðîöåäóðà âûâîäèò ðåçóëüòàò ðàáîòû ôóíêöèè Extract
|
|
// =============================================================================
|
|
procedure ShowManualExtractResult(const ElementName: string;
|
|
Value: TExtractResult);
|
|
begin
|
|
Writeln(Format('%s -> %s', [ElementName,
|
|
GetEnumName(TypeInfo(TExtractResult), Integer(Value))]));
|
|
end;
|
|
|
|
//
|
|
// ñìîòðè îïèñàíèå îáðàáîò÷èêà íèæå
|
|
// =============================================================================
|
|
procedure OnException1(Self, Sender: TObject; E: Exception;
|
|
const ItemIndex: Integer; var Action: TExceptionAction;
|
|
var NewFilePath: string; NewFileData: TMemoryStream);
|
|
var
|
|
CurrentFilePath: string;
|
|
Src: THandleStream;
|
|
Dst: TFileStream;
|
|
hOFStruct: TOFStruct;
|
|
hFile: THandle;
|
|
begin
|
|
CurrentFilePath := string(TFWZipWriter(Sender)[ItemIndex].FilePath);
|
|
NewFilePath := ChangeFileExt(CurrentFilePath, '.tmp');
|
|
hFile := OpenFile(PAnsiChar(AnsiString(CurrentFilePath)),
|
|
hOFStruct, OF_READ);
|
|
try
|
|
Src := THandleStream.Create(hFile);
|
|
try
|
|
Dst := TFileStream.Create(NewFilePath, fmCreate);
|
|
try
|
|
Dst.CopyFrom(Src, 0);
|
|
finally
|
|
Dst.Free;
|
|
end;
|
|
finally
|
|
Src.Free;
|
|
end;
|
|
finally
|
|
CloseHandle(hFile);
|
|
end;
|
|
Action := eaUseNewFilePathAndDel;
|
|
end;
|
|
|
|
//
|
|
// ñìîòðè îïèñàíèå îáðàáîò÷èêà íèæå
|
|
// =============================================================================
|
|
procedure OnException2(Self, Sender: TObject; E: Exception;
|
|
const ItemIndex: Integer; var Action: TExceptionAction;
|
|
var NewFilePath: string; NewFileData: TMemoryStream);
|
|
begin
|
|
CloseHandle(hFile);
|
|
hFile := INVALID_HANDLE_VALUE;
|
|
Action := eaRetry;
|
|
end;
|
|
|
|
//
|
|
// ñìîòðè îïèñàíèå îáðàáîò÷èêà íèæå
|
|
// =============================================================================
|
|
procedure OnException3(Self, Sender: TObject; E: Exception;
|
|
const ItemIndex: Integer; var Action: TExceptionAction;
|
|
var NewFilePath: string; NewFileData: TMemoryStream);
|
|
var
|
|
Src: THandleStream;
|
|
hOFStruct: TOFStruct;
|
|
hFile: THandle;
|
|
begin
|
|
hFile := OpenFile(
|
|
PAnsiChar(AnsiString(TFWZipWriter(Sender)[ItemIndex].FilePath)),
|
|
hOFStruct, OF_READ);
|
|
try
|
|
Src := THandleStream.Create(hFile);
|
|
try
|
|
NewFileData.CopyFrom(Src, 0);
|
|
finally
|
|
Src.Free;
|
|
end;
|
|
finally
|
|
CloseHandle(hFile);
|
|
end;
|
|
Action := eaUseNewFileData;
|
|
end;
|
|
|
|
//
|
|
// ñìîòðè îïèñàíèå îáðàáîò÷èêà íèæå
|
|
// =============================================================================
|
|
procedure OnDuplicate(Self, Sender: TObject;
|
|
var Path: string; var Action: TDuplicateAction);
|
|
begin
|
|
Path := MakeUniqueName(Path);
|
|
Action := daUseNewFilePath;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
SetCurrentDir(ExtractFilePath(ParamStr(0)));
|
|
try
|
|
|
|
// Ñàìàÿ áàíàëüíàÿ îøèáêà ïðè ñîçäàíèè àðõèâà - ýòî îòñóòñòâèå äîñòóïà
|
|
// ê äîáàâëÿåìîìó â àðõèâ ôàéëó.
|
|
// Íàïðèìåð âîò òàêîé êîä ïûòàåòñÿ çààðõèâèðîâàòü ñîäåðæèìîå êîðíåâîé
|
|
// ïàïêè â êîòîðîé èñêóññòâåííî çàëî÷åí îäèí èç ýëåìåíòîâ
|
|
//  ýòîì ñëó÷àå âîçíèêíåò îøèáêà äîñòóïà ê çàëî÷åíîìó ôàéëó.
|
|
// Åñëè íå íàçíà÷åíû îáðàáîò÷èêè èñêëþ÷åíèé, òî òàêîé ôàéë áóäåò ïðîïóùåí
|
|
// (äåéñòâèå ïî óìîë÷àíèþ eaSkip) è ôóíêöèÿ BuildZip
|
|
// âåðíåò ñëåäóþùèå êîäû îøèáîê:
|
|
// brFailed - â ñëó÷àå åñëè â ïàïêå íåáûëî äðóãèõ ôàéëîâ
|
|
// êðîìå çàëî÷åííîãî (ò.å. â àðõèâ äîáàâëÿòü íå÷åãî)
|
|
// brPartialBuild - â ñëó÷àå åñëè â àðõèâ âñå-æå áûëè äîáàâëåíû êàêèå-ëèáî ôàéëû,
|
|
// íî íåêîòîðûå èç íèõ áûëè ïðîïóùåíû
|
|
|
|
Writer := TFWZipWriter.Create;
|
|
try
|
|
Writer.AddFolder('', '..\..\', '*.pas', False);
|
|
ForceDirectories('..\DemoResults\');
|
|
// ëî÷èì îäèí èç ôàéëîâ äëÿ äåìîíñòðàöèè
|
|
hFile := OpenFile(PAnsiChar(AnsiString('..\..\' + Writer[0].FileName)),
|
|
hOFStruct, OF_WRITE);
|
|
try
|
|
Write('BuildWithException1.zip -> ');
|
|
ShowBuildResult(Writer.BuildZip('..\DemoResults\BuildWithException1.zip'));
|
|
finally
|
|
CloseHandle(hFile);
|
|
end;
|
|
finally
|
|
Writer.Free;
|
|
end;
|
|
|
|
// óçíàòü êàêèå ôàéëû áûëè ïðîïóùåíû è ïîïûòàòüñÿ èñïðàâèòü äàííóþ ñèòóàöèþ
|
|
// ìîæíî ïåðåêðûòèåì ñîáûòèÿ OnException
|
|
// Â ñëåäóþùåì ïðèìåðå áóäåò ïîêàçàíî êàê âñå-æå îáðàáîòàòü òàêóþ îøèáêó
|
|
// è äîáàâèòü ïðîáëåìíûé ôàéë â àðõèâ
|
|
|
|
Writer := TFWZipWriter.Create;
|
|
try
|
|
Writer.AddFolder('', '..\..\', '*.pas', False);
|
|
ForceDirectories('..\DemoResults\');
|
|
|
|
// ëî÷èì îäèí èç ôàéëîâ äëÿ äåìîíñòðàöèè
|
|
hFile := OpenFile(PAnsiChar(AnsiString('..\..\' + Writer[0].FileName)),
|
|
hOFStruct, OF_WRITE);
|
|
try
|
|
|
|
// Íàçíà÷àåì îáðàáîò÷èê ÷åðåç êîòîðûé ìû áóäåì îáðàáàòûâàòü îøèáêó
|
|
//  îáðàáîò÷èêå OnException1 áóäåò ñîçäàâàòüñÿ êîïèÿ ôàéëà
|
|
// ïîñëå ÷åãî ìû óêàæåì â ïàðàìåòðå NewFilePath íîâûé ïóòü ê ôàéëó,
|
|
// à ñâîéñòâî Action âûñòàâèì eaUseNewFilePathAndDel
|
|
// Òàêèì îáðàçîì ìû óâåäîìëÿåì FWZip ÷òî íóæíî ïîâòîðèòü ïîïûòêó
|
|
// àðõèâàöèè ôàéëà, ïðè ýòîì íåîáõîäèìî èñïîëüçîâàòü íîâûé ïóòü ê ôàéëó,
|
|
// ïîñëå ÷åãî äàííûé ôàéë ñëåäóåò óäàëèòü.
|
|
|
|
Method.Code := @OnException1;
|
|
Method.Data := Writer;
|
|
Writer.OnException := TZipBuildExceptionEvent(Method);
|
|
|
|
Write('BuildWithException2.zip -> ');
|
|
ShowBuildResult(Writer.BuildZip('..\DemoResults\BuildWithException2.zip'));
|
|
|
|
// âòîðîé âàðèàíò, îáðàáîòêè ïîêàçàí â îáðàáîò÷èêå OnException2
|
|
// â íåì ìû ñíèìàåì èññêóñòâåííóþ áëîêèðîâêó ôàéëà è âûñòàâëÿåì
|
|
// ñâîéñòâî Action â eaRetry.
|
|
// Òàêèì îáðàçîì ìû óâåäîìëÿåì FWZip ÷òî íóæíî ïîâòîðèòü ïîïûòêó
|
|
// àðõèâàöèè ôàéëà
|
|
|
|
Method.Code := @OnException2;
|
|
Method.Data := Writer;
|
|
Writer.OnException := TZipBuildExceptionEvent(Method);
|
|
|
|
Write('BuildWithException3.zip -> ');
|
|
ShowBuildResult(Writer.BuildZip('..\DemoResults\BuildWithException3.zip'));
|
|
|
|
// äëÿ äåìîíñòðàöèè âîçâðàùàåì áëîêèðîâêó íà ìåñòî
|
|
if hFile = INVALID_HANDLE_VALUE then
|
|
hFile := OpenFile(PAnsiChar(AnsiString('..\..\' + Writer[0].FileName)),
|
|
hOFStruct, OF_WRITE);
|
|
|
|
// òðåòèé âàðèàíò, îáðàáîòêè ïîêàçàí â îáðàáîò÷èêå OnException3
|
|
// â íåì ìû çàãðóæàåì ëþáûì ñïîñîáîì äàííûå ôàéëà â ñòðèì è
|
|
// âûñòàâëÿåì ñâîéñòâî Action â eaUseNewFileData
|
|
// Òàêèì îáðàçîì äàííûå áóäóò áðàòüñÿ íåïîñðåäñòâåííî èç ñòðèìà
|
|
// NewFileData
|
|
|
|
Method.Code := @OnException3;
|
|
Method.Data := Writer;
|
|
Writer.OnException := TZipBuildExceptionEvent(Method);
|
|
|
|
Write('BuildWithException4.zip -> ');
|
|
ShowBuildResult(Writer.BuildZip('..\DemoResults\BuildWithException4.zip'));
|
|
|
|
// îðèåíòèðóÿñü íà òèï èñêëþ÷åíèÿ ìîæíî ðåàëèçîâûâàòü ðàçíóëþ ëîãèêó îáðàáîò÷èêà.
|
|
// åñëè âû íå çíàåòå êàê îáðàáîòàòü òî èëè èíîå èñêëþ÷åíèå,
|
|
// ñëåäóåò âûñòàâèòü ñâîéñòâî Action â eaSkip (âûñòàâëåíî ïî óìîë÷àíèþ)
|
|
// äëÿ òîãî ÷òîáû ïðîïóñòèòü ïðîáëåìíûé ôàéë, èëè eaAbort,
|
|
// ïðåðâàâ òàêèì îáðàçîì ñîçäàíèå àðõèâà.
|
|
|
|
finally
|
|
if hFile <> INVALID_HANDLE_VALUE then
|
|
CloseHandle(hFile);
|
|
end;
|
|
finally
|
|
Writer.Free;
|
|
end;
|
|
|
|
// Ïðè ðàñïàêîâêå ÷àñòîé îøèáî÷íîé ñèòóàöèåé ÿâëÿåòñÿ ïîïûòêà
|
|
// ïåðåçàïèñè óæå ñóùåñòâóþùåãî íà äèñêå ôàéëà, ëèáî îøèáêà
|
|
// ðàñïàêîâêè àðõèâà, ñîçäàííîãî ñòîðîííèì àðõèâàòîðîì.
|
|
// Îáðàáîòêà îøèáêè ðàñïàêîâêè ðåøàåòñÿ èñïîëüçîâàíèåì áîëåå
|
|
// íîâîé âåðñèè ZLib (ñì. Readme.txt ïóíêò 9)
|
|
// Âîçíèêíîâåíèå îøèáêè ïî äðóãèì ïðè÷èíàì ïðèâåäåò ê âîçíèêíîâåíèþ
|
|
// ñîáûòèÿ OnException. Åñëè äàííîå ñîáûòèå íå ïåðåêðûòî,
|
|
// òî â ñëó÷àå âûçîâà ìåòîäà TFWZipReader.ExtractAll
|
|
// ðàñïàêîâêà àðõèâà áóäåò îñòàíîâëåíà.
|
|
//  ñëó÷àå, åñëè äàííîå ñîáûòèå ïåðåêðûòî, òî ðåøåíèå
|
|
// î îñòàíîâêå ðàñïàêîâêè äîëæåí ïðèíèìàòü ïðîãðàììèñò,
|
|
// âûñòàâëåíèåì ôëàãà Handled:
|
|
// (Handled = True, èñêëþ÷åíèå îáðàáîòàíî, ìîæíî ïðîäîëæèòü ðàñïàêîâêó)
|
|
|
|
// äëÿ äåìîíñòðàöèè ïðîýìóëèðóåì îøèáêó ïåðåçàïèñè,
|
|
// äëÿ ýòîãî íóæíî äâàæäû ðàñïàêîâàòü îäèí è òîò-æå àðõèâ
|
|
// â îäíó è òó-æå ïàïêó
|
|
|
|
Reader := TFWZipReader.Create;
|
|
try
|
|
Reader.LoadFromFile('..\DemoResults\BuildWithException1.zip');
|
|
ForceDirectories('..\DemoResults\BuildWithExceptionUnpack\');
|
|
|
|
// ðàñïàêîâûâàåì ïåðâûé ðàç
|
|
|
|
Reader.ExtractAll('..\DemoResults\BuildWithExceptionUnpack\');
|
|
|
|
// òåïåðü ïðîáóåì ðàñïàêîâàòü ïîâòîðíî.
|
|
// èñêëþ÷åíèÿ â äàííîì ñëó÷àå íå ïðîèçîéäåò, íî âñå ýëåìåíòû áóäóò ïðîïóùåíû
|
|
|
|
Reader.ExtractAll('..\DemoResults\BuildWithExceptionUnpack\');
|
|
|
|
// ïðîïóñê ýëåìåíòîâ ìîæíî óâèäåòü è ïðè ðó÷íîé ðàñïàêîâêå.
|
|
// ò.ê. âûçîâ Reader[I].Extract â îòëè÷èå îò Reader.ExtractAll
|
|
// âîçâðàùàåò ðåçóëüòàò
|
|
|
|
Writeln('Manual extract:');
|
|
for I := 0 to Reader.Count - 1 do
|
|
ShowManualExtractResult(
|
|
string(Reader[I].FileName),
|
|
Reader[I].Extract('..\DemoResults\BuildWithExceptionUnpack\', ''));
|
|
|
|
// êàê ìîæíî çàìåòèòü, âñå ýëåìåíòû äåéñòâèòåëüíî áûëè ïðîïóùåíû
|
|
// (Reader[I].Extract âåðíóë erSkiped äëÿ êàæäîãî ýëåìåíòà)
|
|
|
|
// Äëÿ îáðàáîòêè äàííîé ñèòóàöèè â ðåæèìå àâòîìàòè÷åñêîé ðàñïàêîâêè (ExtractAll)
|
|
// íåîáõîäèìî ïåðåêðûòü ñîáûòèå OnDuplicate ó êëàññà TFWZipReader.
|
|
//  ñëó÷àå ðó÷íîé ðàñïàêîâêè, ïåðåêðûâàòü ñîáûòèå OnDuplicate òðåáóåòñÿ
|
|
// ó êàæäîãî ýëåìåíòà (Reader.Items[èíäåêñ ýëåìåíòà].OnDuplicate)
|
|
|
|
Method.Code := @OnDuplicate;
|
|
Method.Data := Reader;
|
|
Reader.OnDuplicate := TZipDuplicateEvent(Method);
|
|
|
|
// òåïåðü ïîïðîáóåì ïîâòîðíî ðàñïàêîâàòü.
|
|
// ïðè âîçíèêíîâåíèè ñîáûòèÿ OnDuplicate â îáðàáîò÷èêå ýëåìåíòó áóäåò
|
|
// íàçíà÷åíî íîâîå èìÿ è ïàðàìåòð Action áóäåò âûñòàâëåí â daUseNewFilePath.
|
|
// Òàêèì îáðàçîì ìû óêàæåì TFWZipReader-ó ÷òî íåîáõîäèìî ðàñïàêîâàòü
|
|
// ôàéë ñ íîâûì èìåíåì...
|
|
// (ò.å. ïîëó÷èì àíàëîã ñîçäàíèÿ ôàéëîâ â ïðîâîäíèêå Windows, íàïðèìåð:
|
|
// New folder -> New folder (2) -> New folder (3) è ò.ä.)
|
|
|
|
Reader.ExtractAll('..\DemoResults\BuildWithExceptionUnpack\');
|
|
|
|
finally
|
|
Reader.Free;
|
|
end;
|
|
|
|
except
|
|
on E: Exception do
|
|
Writeln(E.ClassName, ': ', E.Message);
|
|
end;
|
|
Readln;
|
|
end.
|