Delphi XE2 TZipFile: replace a file in zip archive

前端 未结 1 1533
灰色年华
灰色年华 2021-02-15 18:37

I\'d like to replace a file (= delete old and add new) in a zip archive with the Delphi XE2/XE3 standard System.Zip unit. But there are no replace/delete methods. Does anybody h

1条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-02-15 19:19

    I'd recommend Abbrevia because I'm biased :), you already know it, and it doesn't require any hacks. Barring that, here's 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;
    

    Usage:

    ZipFile.Delete('document.txt');
    ZipFile.Add(SS, 'document.txt');
    

    0 讨论(0)
提交回复
热议问题