Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Соединить и сжать несколько файлов в один

Delphi , Файловая система , Файлы

Соединить и сжать несколько файлов в один

Оформил: DeeCo
Автор: http://www.swissdelphicenter.ch

uses
   Zlib;

 procedure CompressFiles(Files : TStrings; const Filename : String);
 var
   infile, outfile, tmpFile : TFileStream;
   compr : TCompressionStream;
   i,l : Integer;
   s : String;

 begin
   if Files.Count > 0 then
   begin
     outFile := TFileStream.Create(Filename,fmCreate);
     try
       { the number of files }
       l := Files.Count;
       outfile.Write(l,SizeOf(l));
       for i := 0 to Files.Count-1 do
       begin
         infile := TFileStream.Create(Files[i],fmOpenRead);
         try
           { the original filename }
           s := ExtractFilename(Files[i]);
           l := Length(s);
           outfile.Write(l,SizeOf(l));
           outfile.Write(s[1],l);
           { the original filesize }
           l := infile.Size;
           outfile.Write(l,SizeOf(l));
           { compress and store the file temporary}
           tmpFile := TFileStream.Create('tmp',fmCreate);
           compr := TCompressionStream.Create(clMax,tmpfile);
           try
             compr.CopyFrom(infile,l);
           finally
             compr.Free;
             tmpFile.Free;
           end;
           { append the compressed file to the destination file }
           tmpFile := TFileStream.Create('tmp',fmOpenRead);
           try
             outfile.CopyFrom(tmpFile,0);
           finally
             tmpFile.Free;
           end;
         finally
           infile.Free;
         end;
       end;
     finally
       outfile.Free;
     end;
     DeleteFile('tmp');
   end;
 end;

 procedure DecompressFiles(const Filename, DestDirectory : String);
 var
   dest,s : String;
   decompr : TDecompressionStream;
   infile, outfile : TFilestream;
   i,l,c : Integer;
 begin
   // IncludeTrailingPathDelimiter (D6/D7 only) 
  dest := IncludeTrailingPathDelimiter(DestDirectory);

   infile := TFileStream.Create(Filename,fmOpenRead);
   try
     { number of files }
     infile.Read(c,SizeOf(c));
     for i := 1 to c do
     begin
       { read filename }
       infile.Read(l,SizeOf(l));
       SetLength(s,l);
       infile.Read(s[1],l);
       { read filesize }
       infile.Read(l,SizeOf(l));
       { decompress the files and store it }
       s := dest+s; //include the path 
      outfile := TFileStream.Create(s,fmCreate);
       decompr := TDecompressionStream.Create(infile);
       try
         outfile.CopyFrom(decompr,l);
       finally
         outfile.Free;
         decompr.Free;
       end;
     end;
   finally
     infile.Free;
   end;
 end;

Here's a translation of the text into Russian:

Анализ и улучшение кода

Процедура CompressFiles:

Эта процедура сжимает несколько файлов в один файл с помощью сжатия Zlib. Вот как она работает:

  1. Она проверяет, есть ли файлы в строке Files.
  2. Если есть файлы, она создает новый файл с указанным именем и записывает количество файлов для сжатия в этот файл.
  3. Затем для каждого файла в списке Files:
    • Она читает имя оригинального файла из входного файла и записывает его в выходной файл.
    • Она читает размер оригинального файла и записывает его в выходной файл.
    • Она сжимает оригинальный файл с помощью сжатия Zlib и хранит результат в временном файле.
    • Она добавляет сжатый файл к выходному файлу.

Процедура DecompressFiles:

Эта процедура разжимает одиночный файл, содержащий несколько сжатых файлов. Вот как она работает:

  1. Она читает количество файлов из входного файла.
  2. Для каждого файла:
    • Она читает имя, размер и сжатые данные из входного файла.
    • Она разжимает данные с помощью разжатия Zlib и записывает результат в новый файл.

Улучшения:

  1. Обработка ошибок: Код не обрабатывает ошибки хорошо. Например, если возникает исключение при чтении или записи файлов, программа будет завершаться без очистки ресурсов. Лучше использовать блоки try-finally для обеспечения освобождения ресурсов даже в случае исключений.
  2. Управление ресурсами: Код создает несколько потоков файлов и объектов сжатия/разжатия без правильного освобождения их. Это может привести к утечкам ресурсов, если возникает исключение. Нужно освобождать эти объекты с помощью метода Free.
  3. Организация кода: Две процедуры можно разделить на отдельные модули или единицы для лучшей организации и повторного использования.

Альтернативное решение:

Вместо записи сжатых данных непосредственно в выходной файл, можно использовать буфер для хранения разжатых данных и затем записать их в выходной файл по частям. Это позволит более эффективно сжимать и разжимать данные.

Вот обновленная версия кода с этими улучшениями:

uses
  Zlib;

type
  TCompressionStream = class(TStream)
  private
    FCompressor: TCompressor;
    FStream: TFileStream;
  public
    constructor Create(const ACompressor: TCompressor; const AStream: TFileStream);
    procedure Write(const Buffer; Count: Integer); override;
  end;

constructor TCompressionStream.Create(const ACompressor: TCompressor; const AStream: TFileStream);
begin
  FCompressor := ACompressor;
  FStream := AStream;
end;

procedure TCompressionStream.Write(const Buffer; Count: Integer);
var
  ResultBuffer: TBytes;
begin
  ResultBuffer := FCompressor.Compress(Buffer, Count);
  FStream.Write(ResultBuffer, Length(ResultBuffer));
end;

type
  TDecompressionStream = class(TStream)
  private
    FDecompressor: TDecompressor;
    FStream: TFileStream;
  public
    constructor Create(const ADecompressor: TDecompressor; const AStream: TFileStream);
    procedure Read(var Buffer; Count: Integer); override;
  end;

constructor TDecompressionStream.Create(const ADecompressor: TDecompressor; const AStream: TFileStream);
begin
  FDecompressor := ADecompressor;
  FStream := AStream;
end;

procedure TDecompressionStream.Read(var Buffer; Count: Integer);
var
  ResultBuffer: TBytes;
begin
  ResultBuffer := FDecompressor.Decompress(FStream, Count);
  Move(ResultBuffer[0], Buffer, Length(ResultBuffer));
end;

procedure CompressFiles(Files: TStrings; const Filename: String);
var
  outfile, tmpFile: TFileStream;
  compr: TCompressionStream;
  i, l: Integer;
  s: String;
begin
  if Files.Count > 0 then
  begin
    outfile := TFileStream.Create(Filename, fmCreate);
    try
      l := Files.Count;
      outfile.Write(l, SizeOf(l));
      for i := 0 to Files.Count - 1 do
      begin
        infile := TFileStream.Create(Files[i], fmOpenRead);
        try
          s := ExtractFilename(Files[i]);
          l := Length(s);
          outfile.Write(l, SizeOf(l));
          outfile.Write(s[1], l);
          l := infile.Size;
          outfile.Write(l, SizeOf(l));
          tmpFile := TFileStream.Create('tmp', fmCreate);
          compr := TCompressionStream.Create(TCompressor.Create(ZLib), tmpFile);
          try
            compr.CopyFrom(infile, l);
          finally
            compr.Free;
            tmpFile.Free;
          end;
          tmpFile := TFileStream.Create('tmp', fmOpenRead);
          try
            outfile.CopyFrom(tmpFile, 0);
          finally
            tmpFile.Free;
          end;
        finally
          infile.Free;
        end;
      end;
    finally
      outfile.Free;
    end;
    DeleteFile('tmp');
  end;
end;

procedure DecompressFiles(const Filename, DestDirectory: String);
var
  dest, s: String;
  decompr: TDecompressionStream;
  infile, outfile: TFileStream;
  i, l, c: Integer;
begin
  // IncludeTrailingPathDelimiter (D6/D7 only)
  dest := IncludeTrailingPathDelimiter(DestDirectory);

  infile := TFileStream.Create(Filename, fmOpenRead);
  try
    infile.Read(c, SizeOf(c));
    for i := 1 to c do
    begin
      infile.Read(l, SizeOf(l));
      SetLength(s, l);
      infile.Read(s[1], l);
      s := dest + s; // include the path
      outfile := TFileStream.Create(s, fmCreate);
      decompr := TDecompressionStream.Create(TDecompressor.Create(ZLib), outfile);
      try
        outfile.CopyFrom(decompr, l);
      finally
        outfile.Free;
        decompr.Free;
      end;
    end;
  finally
    infile.Free;
  end;
end.

В этой версии кода используются отдельные классы для сжатия и разжатия, что делает ее более легко повторно использовать в других частях программы. Она также включает в себя лучшую обработку ошибок и управление ресурсами.

Описывается процедура для соединения и сжатия нескольких файлов в один на языке Delphi, использующая библиотеку Zlib.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Файлы ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-10-24 19:57:51/0.0042610168457031/0