Delphi XE2 TZipFile: replace a file in a zip archive

I want to replace the file (= delete the old and add a new one) to the zip archive using the standard element System.Zip Delphi XE2 / XE3. But there are no replacement / removal methods. Does anyone know how this could be achieved without having to extract all the files and add them to the new archive?

I have this code, but it adds "document.txt" again if it is already present:

var ZipFile: TZipFile; SS: TStringStream; const ZipDocument = 'E:\document.zip'; begin ZipFile := TZipFile.Create; //Zipfile: TZipFile SS := TStringStream.Create('hello'); try if FileExists(ZipDocument) then ZipFile.Open(ZipDocument, zmReadWrite) else ZipFile.Open(ZipDocument, zmWrite); ZipFile.Add(SS, 'document.txt'); ZipFile.Close; finally SS.Free; ZipFile.Free; end; end; 

Note. I used to use TPAbbrevia (this did the job), but now I would like to use the Delphi Zip module. Therefore, please do not respond to something like "use another library." Thanks.

+8
delphi zip delphi-xe3 delphi-xe2
source share
1 answer

I would recommend Abbrevia because I am biased :) you already know this and it does not require any hacks. Ban on here is your hack:

 type TZipFileHelper = class helper for TZipFile procedure Delete(FileName: string); end; { TZipFileHelper } procedure TZipFileHelper.Delete(FileName: string); var i, j: Integer; StartOffset, EndOffset, Size: UInt32; Header: TZipHeader; Buf: TBytes; begin i := IndexOf(FileName); if i <> -1 then begin // Find extents for existing file in the file stream StartOffset := Self.FFiles[i].LocalHeaderOffset; EndOffset := Self.FEndFileData; for j := 0 to Self.FFiles.Count - 1 do begin if (Self.FFiles[j].LocalHeaderOffset > StartOffset) and (Self.FFiles[j].LocalHeaderOffset <= EndOffset) then EndOffset := Self.FFiles[j].LocalHeaderOffset; end; Size := EndOffset - StartOffset; // Update central directory header data Self.FFiles.Delete(i); for j := 0 to Self.FFiles.Count - 1 do begin Header := Self.FFiles[j]; if Header.LocalHeaderOffset > StartOffset then begin Header.LocalHeaderOffset := Header.LocalHeaderOffset - Size; Self.FFiles[j] := Header; end; end; // Remove existing file stream SetLength(Buf, Self.FEndFileData - EndOffset); Self.FStream.Position := EndOffset; if Length(Buf) > 0 then Self.FStream.Read(Buf[0], Length(Buf)); Self.FStream.Size := StartOffset; if Length(Buf) > 0 then Self.FStream.Write(Buf[0], Length(Buf)); Self.FEndFileData := Self.FStream.Position; end; end; 

Using:

 ZipFile.Delete('document.txt'); ZipFile.Add(SS, 'document.txt'); 
+12
source share

All Articles