Delphi XE2 TZipFile:替换zip存档中的文件 [英] Delphi XE2 TZipFile: replace a file in zip archive

查看:116
本文介绍了Delphi XE2 TZipFile:替换zip存档中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Delphi XE2/XE3标准System.Zip单元替换zip存档中的文件(=删除旧文件并添加新文件).但是没有替换/删除方法.有没有人知道如何在不需要提取所有文件并将其添加到新存档的情况下实现该目标?

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 have an idea how it could be achieved without needing to extract all files and add them to a new archive?

我有这段代码,但是如果已经存在,它将再次添加"document.txt":

I have this code, but it adds the "document.txt" once more if it's 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;

注意:我以前使用过TPAbbrevia(完成了这项工作),但是现在我想使用Delphi的Zip单元.因此,请不要回答诸如使用另一个库"之类的问题.谢谢.

Note: I used TPAbbrevia before (that did the job), but I'd like to use Delphi's Zip unit now. So please do not answer something like "use another library". Thank you.

推荐答案

我建议Abbrevia,因为我有偏见:),您已经知道了,它不需要任何技巧.除非如此,这就是您的骇客:

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;

用法:

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

这篇关于Delphi XE2 TZipFile:替换zip存档中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆