Спасибо, что Вы выбрали наш форум. Я надеюсь, что именно здесь Вы найдете ответы на все свои вопросы.
С уважением Булай Никита.
Форум по программированию в Delphi |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » Форум по программированию в Delphi » Система и Delphi » Программирование системы в Delphi
Спасибо, что Вы выбрали наш форум. Я надеюсь, что именно здесь Вы найдете ответы на все свои вопросы.
С уважением Булай Никита.
Здрасте! Подскажите пож-ста, что делать в такой ситуации: есть папка с файлами, нужно, чтобы программа брала и сжимала всё, что есть в этой папке в один компактный инсталлер. Буду рад ответу с приведенным кодом программы.
При программировании может возникнуть потребность собрать все содержимое папки (включая ее подпапки) в один файл, из которого можно потом обратно восстановить всю структуру упакованной папки. Подобным методом пользуются архиваторы, когда пользователь сжимает не один файл, а целиком папку или несколько файлов. В рассматриваемом здесь варианте никакого сжатия не предполагается. Ниже приведен модуль, позволяющий упаковать папку в файл, не производя сжатия данных и восстановить содержимое папки по упакованному файлу:
Code (Pascal):
unit Folders;
////////////////////////////////////////////////////////////////////////////////
// //
// М О Д У Л Ь П Р Е О Б Р А З О В А Н И Я П А П К И В Ф А Й Л //
// //
// И О Б Р А Т Н О //
// //
// А В Т О Р : А К А Т О В А Л Е К С Е Й //
// //
////////////////////////////////////////////////////////////////////////////////
interface
uses Windows, SysUtils, Forms;
function DirToFile (DirName, FileName: string): Integer;
function FileToDir (FileName, DirName: string): Integer;
implementation
(* uses UProgress; *)
const BufSize = $FFFF;
var Buf: array[0..BufSize] of Byte;
function DirWork (Dir, Path: string; H: Integer): Integer;
// Рекурсивная обработка дерева папок:
var FSR: TSearchRec;
Size, FIn, Sz, Md, Pt: Integer;
FName: string;
begin
{$I-}
if FindFirst (Concat (Dir, Path, '\*.*') , faAnyFile, FSR) = 0 then
begin
repeat
if (FSR.Name <> '.') and (FSR.Name <> '..') then
begin
if Path <> '' then FName := Concat (Path, '\', FSR.Name)
else FName := FSR.Name;
(* FProgress.CaptPanel.Caption := FName; // FProgress - это форма в Delphi
FProgress.Gauge1.MinValue := 0;
FProgress.Gauge1.Progress := 0; *)
FileWrite (H, FSR.Attr, SizeOf (FSR.Attr));
Size := Length (FName);
FileWrite (H, Size, SizeOf (Size));
FileWrite (H, FName[1], Size);
if (FSR.Attr and faDirectory) <> 0 then
begin {папка:}
Result := DirWork (Dir, FName, H);
if Result <> 0 then Exit;
end else
begin {файл:}
FIn := FileOpen (Concat (Dir, FName), fmOpenRead or fmShareDenyWrite);
Size := GetFileSize (FIn, nil);
(* FProgress.Gauge1.MaxValue := Size; *)
if SizeOf (Buf) > 0 then Md := (Size div SizeOf (Buf)) div 100
else Md := 16;
if Md = 0 then Md := 1;
if Md > 16 then Md := 16;
Sz := 0;
FileWrite (H, Size, SizeOf (Size));
repeat
Size := FileRead (FIn, Buf, SizeOf (Buf));
if Size > 0 then FileWrite (H, Buf, Size);
Inc (Sz, Size);
if Pt mod Md = 0 then
begin
(* FProgress.Gauge1.Progress := Sz; *)
Application.ProcessMessages;
end; {if}
Inc (Pt);
until Size <= 0;
Application.ProcessMessages;
FileClose (FIn);
end; {if}
end; {if}
until FindNext (FSR) <> 0;
FindClose (FSR);
end; {if}
{$I+}
Result := IOResult;
end; {func DirWork}
function DirToFile (DirName, FileName: string): Integer;
// Преобразовать папку в файл:
var H, Res: Integer;
F: file of Byte;
begin
try
(* Application.CreateForm(TFProgress, FProgress);
FProgress.Show; *)
{$I-}
AssignFile (F, FileName);
Rewrite (F);
CloseFile (F);
H := FileOpen (FileName, fmOpenWrite);
Result := DirWork (Concat (DirName, '\'), '', H);
FileClose (H);
{$I+}
Res := IOResult;
if Res <> 0 then Result := Res;
except
Result := 1;
end; {try}
(* FProgress.Free; *)
end; {func DirToFile}
function FileToDir (FileName, DirName: string): Integer;
// Преобразовать файл в папку:
var H, FOut, Size, Sz, Attr, Md, Pt, MaxSz: Integer;
F: file of Byte;
FName: string;
P: PChar;
begin
try
(* Application.CreateForm(TFProgress, FProgress);
FProgress.Show; *)
{$I-}
if not DirectoryExists (DirName) then MkDir (DirName);
H := FileOpen (FileName, fmOpenRead or fmShareDenyWrite);
repeat
if FileRead (H, Attr, SizeOf (Attr)) <= 0 then Break;
FileRead (H, Size, SizeOf (Size));
GetMem (P, Size);
FileRead (H, P^, Size);
SetString (FName, P, Size);
FreeMem (P);
(* FProgress.CaptPanel.Caption := FName;
FProgress.Gauge1.MinValue := 0;
FProgress.Gauge1.Progress := 0; *)
FName := Concat (DirName, '\', FName);
if (Attr and faDirectory) <> 0 then
begin {папка:}
if not DirectoryExists (FName) then MkDir (FName);
end else
begin {файл:}
FileRead (H, Size, SizeOf (Size));
AssignFile (F, FName);
Rewrite (F);
CloseFile (F);
FOut := FileOpen (FName, fmOpenWrite);
if SizeOf (Buf) > 0 then Md := (Size div SizeOf (Buf)) div 100
else Md := 16;
if Md = 0 then Md := 1;
if Md > 16 then Md := 16;
(* FProgress.Gauge1.MaxValue := Size; *)
MaxSz := Size;
Pt := 0;
repeat
if Size > SizeOf (Buf) then Sz := SizeOf (Buf)
else Sz := Size;
FileRead (H, Buf, Sz);
FileWrite (FOut, Buf, Sz);
Dec (Size, Sz);
if Pt mod Md = 0 then
begin
(* FProgress.Gauge1.Progress := MaxSz - Size; *)
Application.ProcessMessages;
end; {if}
Inc (Pt);
until Size <= 0;
Application.ProcessMessages;
Fileclose (FOut);
end; {if}
FileSetAttr (FName, Attr);
until False;
FileClose (H);
{$I+}
Result := IOResult;
except
Result := 1;
end; {try}
(* FProgress.Free; *)
end; {func FileToFile}
end.
Модуль содержит две функции:
function DirToFile (DirName, FileName: string): Integer; - упаковывает указанную папку DirName в файл с именем FileName.
function FileToDir (FileName, DirName: string): Integer; - распаковывает упакованный файл с именем FileName в папку с именем DirName.
Функции возвращают целочисленный результат, показывающий код ошибки. Если он равен нулю - операция прошла успешно.
Если упаковываемые папки не очень большие (в пределах 10 Мегабайт), то время, затрачиваемое на выполнение этих функций незначительное. Однако процесс упаковывания больших папок может занять существенное время. Для этого желательно вывести некоторый прогрессбар на экран пользователя, что бы у него не сложилось впечатления, что программа зависла. Для этого нужно убрать все комментарии в модуле, заключенные в скобки: (* и *). Кроме этого нужно создать модуль UProgress с формой FProgress, на которой разместить компонент с именем Gauge1 типа TGauge (закладка Samples палитры компонентов). Этот визуальный компонент и будет служить прогрессбаром, показывающем процент завершенности операции.
Однако надо обратить внимание на то, что создать упакованный файл размером более 4 Гигабайт не удастся - это максимальный размер файла, с которым может работать описываемый модуль.
А сжать файл можно с помощью zLib или другого похожего компонента!
Спасибо! А как этим зЛиб'ом упаковать?
Надо подключить модуль zLib -
Uses ..., zlib, вроде так называется. А далее использовать приведенные в нем функции и процедуры.
Скачал с Вашего сайта Аманду Инсталлер. По какой-то причине пакует только папки, а файлы - нет.
Потому что использует выше приведенный код. Просто все файлы и папки копируются в папку Temp, а затем упаковываются в инсталлятор.
Я пробовал даже сразу закидывать всё в эту папку - всё равно пакует только папки. У меня было несколько папок общим объёмом 50 Мб, а после упаковки выходной файл стал 300 Кб. Так даже WinRar и 7-Zip не сжимают! Я распаковал, а оказалось, что все папки пусты, т.е. в директории установки папки есть, а файлов в них нет.
Возможно у тебя какая-нибудь ошибка в коде. Проверь все досканально. Советую каждое действие записывать в Memo или отдельный файл, чтоб понять, если где-то ошибочка.
Я это писал про аманду
А, не знаю, у меня все получается нормально. Возможно ты что-то не так делаешь. А вообще юзать Inno Setup.
инно платный - ну его
Согласен. Тему закрываем.
Вы здесь » Форум по программированию в Delphi » Система и Delphi » Программирование системы в Delphi