Едут в переполненном автобусе качок, каратист и программист. Измученный толкотней качок предлагает:
- Давайте, ребята, поднажмем и лишний народ вытолкнем.
Каратист не согласен:
- Да, ну, давайте лучше замочим человек пять, а остальные сами разбегутся.
Программист с умным лицом предлагает:
- Зачем мучиться, давайте лучше заархивируем всех и положим на переднее сиденье.
// Объявленияfunction RAROpenArchive(ArchiveData : Pointer): Integer; stdcall;
external 'unrar.dll' name 'RAROpenArchive';
function RARCloseArchive(hArcData : Integer): Integer; stdcall;
external 'unrar.dll' name 'RARCloseArchive';
function RARReadHeader(hArcData : Integer; HeaderData : Pointer):
Integer; stdcall;
external 'unrar.dll' name 'RARReadHeader';
function RARProcessFile(hArcData : Integer; Operation : Integer;
DestPath : Pointer; DestName : Pointer): Integer; stdcall;
external 'unrar.dll' name 'RARProcessFile';
const
ERAR_END_ARCHIVE = 10;
ERAR_NO_MEMORY = 11;
ERAR_BAD_DATA = 12;
ERAR_BAD_ARCHIVE = 13;
ERAR_UNKNOWN_FORMAT = 14;
ERAR_EOPEN = 15;
ERAR_ECREATE = 16;
ERAR_ECLOSE = 17;
ERAR_EREAD = 18;
ERAR_EWRITE = 19;
ERAR_SMALL_BUF = 20;
RAR_OM_LIST = 0;
RAR_OM_EXTRACT = 1;
RAR_SKIP = 0;
RAR_TEST = 1;
RAR_EXTRACT = 2;
RAR_VOL_ASK = 0;
RAR_VOL_NOTIFY = 1;
type
Char260 = array [1..260] of Char;
TRAROpenArchiveData = record
ArcName : PChar; // в C++ это будет выглядеть как: char *ArcName
OpenMode : Cardinal;
OpenResult : Cardinal;
CmtBuf : PChar;
CmtBufSize : Cardinal;
CmtSize : Cardinal;
CmtState : Cardinal;
end;
TRARHeaderData = record
ArcName : Char260;
FileName : Char260;
Flags : Cardinal;
PackSize : Cardinal;
UnpSize : Cardinal;
HostOS : Cardinal;
FileCRC : Cardinal;
FileTime : Cardinal;
UnpVer : Cardinal;
Method : Cardinal;
FileAttr : Cardinal;
CmtBuf : PChar;
CmtBufSize : Cardinal;
CmtSize : Cardinal;
CmtState : Cardinal;
end;
var
RARExtract : boolean;
RAROpenArchiveData : TRAROpenArchiveData;
RARComment : array [1..256] of Char;
RARHeaderData : TRARHeaderData;
...
procedure ExtractRARArchive;
var
sDir : string;
s : string;
sTest : string;
iTest : integer;
bTestDone : boolean;
RARhnd : Integer;
RARrc : Integer;
PDestPath : Char260;
begin
RARExtract:=TRUE;
lKBWritten:=0;
ProgressBar2.Position := 0;
ProgressBar2.Max := lTotalSize;
RARStartTime:=Time;
RAROpenArchiveData.OpenResult:=99;
RAROpenArchiveData.OpenMode := RAR_OM_EXTRACT; // открываем для распаковки
RAROpenArchiveData.ArcName:= @RARFileName;
RAROpenArchiveData.CmtBuf := @RARComment;
RAROpenArchiveData.CmtBufSize := 255;
// Открываем RAR архив и выделяем память
RARhnd := RAROpenArchive (@RAROpenArchiveData);
if RAROpenArchiveData.OpenResult <> 0 thenbegincase RAROpenArchiveData.OpenResult of
ERAR_NO_MEMORY : s:='Not enough memory to initialize data structures';
ERAR_BAD_DATA : s:='Archive header broken';
ERAR_BAD_ARCHIVE : s:='File is not valid RAR archive';
ERAR_EOPEN : s:='File open error';
end;
MessageDlg('Unable to open rar archive: ' + s + '!',mtError, [mbOK], 0);
end;
RARSetProcessDataProc(RARhnd,@Form.OnRarStatus);
StrPCopy(@PDestPath, EInstallPath.Text);
repeat
RARrc := RARReadHeader (RARhnd, @RARHeaderData);// Читаем заголовокif RARrc <> ERAR_END_ARCHIVE thenbegin
ProgressBar1.Position := 0;
ProgressBar1.Max := RARHeaderData.UnpSize;
s:=RARHeaderData.FileName;
lblCurrentFile.Caption := s;
lKBytesDone := 0;
end;
if RARrc = 0 then
RARrc:=RARProcessFile (RARhnd, RAR_EXTRACT, @PDestPath, nil);
if (RARrc <> 0) and (RARrc <> ERAR_END_ARCHIVE) thenbegin
MessageDlg('An Error occured during extracting of ' + sTest+'!' + #13#10 +
'RARProcessFile: ' + MakeItAString(RARrc),mtError, [mbOK], 0);
end;
until
RARrc <> 0;
// закрываем RAR архив и освобождаем памятьif RARCloseArchive(RARhnd) <> 0 thenbegin
MessageDlg('Unable to close rar archive!',mtError, [mbOK], 0);
end;
end;
Перед тем, как мы начнем обзор кода и предложения, хотел бы обратить внимание, что использование внешнего DLL-файла, такого как unrar.dll, может быть хорошей идеей, но также ограничивает портативность и поддержку вашего программного обеспечения.
Теперь давайте более подробно рассмотрим код:
Декларации функций
Функциональные декларации для RAROpenArchive, RARCloseArchive, RARReadHeader и RARProcessFile корректны. Однако, вам может быть полезно использовать более описательное наименование для этих функций, например, OpenRarArchive, CloseRarArchive и т.д.
Константные определения
Константные определения для кодов ошибок (например, ERAR_END_ARCHIVE) и других значений (например, RAR_OM_EXTRACT) полезны. Вам может быть полезно группировать их в отдельный модуль или единицу для лучшей организации кода.
Типовые определения
Типовые определения для TRAROpenArchiveData и TRARHeaderData корректны. Однако, вам может быть полезно добавить комментарии, объясняющие, что каждый поле представляет собой.
Декларации переменных
Декларации переменных для RARExtract, RAROpenArchiveData, RARComment и т.д. корректны.
Процедура ExtractRARArchive
Эта процедура является основным точкой входа для извлечения архива RAR. Вот некоторые предложения:
Обработка ошибок: Вы уже проверяете ошибки в RAROpenArchive и RARCloseArchive. Однако, вам может быть полезно реализовать более robust обработку ошибок по всему процессу.
Обновление прогресс-бара: Вы обновляете прогресс-бар вручную, используя ProgressBar1.Position и ProgressBar1.Max. Вам может быть полезно использовать более эффективный подход, например, свойство TProgressBar.Progress или реализовать свою механику обновления прогресс-бара.
Цикл извлечения файлов: Цикл извлечения файлов использует конструкцию repeat...until, чтобы извлечь файлы из архива RAR. Вам может быть полезно разбить это на отдельные процедуры или функции для лучшей организации кода и читаемости.
Обработка строк: Вы используете конкатенацию строк, чтобы построить сообщения об ошибках в нескольких местах. Вам может быть полезно использовать более эффективный подход, например, функцию Format или реализовать свою механику создания сообщений об ошибках.
Альтернативное решение
Если вы ищете альтернативное решение, вам может быть полезно рассмотреть использование библиотеки Delphi, которая предоставляет возможности извлечения архивов RAR без использования внешнего DLL-файла, такого как unrar.dll. Например, вы можете использовать компонент RarArchive из библиотеки SynEdit или реализовать свою логику извлечения архивов RAR с помощью встроенных ZIP и TAR-библиотек Delphi.
Надеюсь, это поможет! Пожалуйста, дайте мне знать, если у вас есть какие-либо дополнительные вопросы.
Создаём собственный UnRar, используя unrar.dll: в статье рассматривается создание программы для распаковки архивов RAR с использованием функций из динамической библиотеки unrar.dll.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.