我想用Delphi XE2 / XE3标准System.Zip单元替换zip存档中的文件(= delete old和add new).但是没有替换/删除方法.有没有人知道如何在不需要提取所有文件并将其添加到新存档的情况下实现它?
我有这个代码,但如果它已经存在,它会再次添加“document.txt”:
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;
注意:我之前使用过TPAbbrevia(完成了这项工作),但我现在想使用Delphi的Zip单元.所以请不要回答“使用其他图书馆”之类的内容.谢谢.
解决方法
我推荐Abbrevia因为我有偏见:),你已经知道了,它不需要任何黑客攻击.除此之外,这是你的黑客:
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;
用法:
ZipFile.Delete('document.txt'); ZipFile.Add(SS,'document.txt');