Delphi:从流中打开一个zip存档 - >提取到流

时间:2012-01-17 08:56:16

标签: delphi stream load zip extract

是否有任何具有此类功能的zip组件?我需要将一个zip存档从Internet下载到一个流,然后从流中打开存档,然后将文件解压缩到另一个流。

E.g。 ZipForge 可以从流ZipForge.OpenArchive(MyStream, false);打开存档 但如何提取到另一个......?

procedure ExtractToStream(FileName: WideString; Stream: TStream); 

说明

  

使用ExtractToStream解压缩存储在文件内的数据   存档到Tileream后代对象,如TFileStream,TMemoryStream   或TBlobStream。

     

FileName参数指定要提取的文件名。

如果不支持提取,则使用OpenArchive(MyStream, false)方法...

1 个答案:

答案 0 :(得分:22)

XE2中内置的zip文件组件将执行此操作。

有一个重载的Open方法,它接收TStream作为输入参数。

要提取单个文件,您可以调用重载的Read方法,传递要提取的文件的名称。提取的文件作为TStream的新实例返回。您可以使用该实例上的CopyFrom将提取的文件传输到您的流中。

var
  ZipFile: TZipFile;
  DownloadedStream, DecompressionStream, MyStream: TStream;
  LocalHeader: TZipHeader;
...
ZipFile := TZipFile.Create;
try
  ZipFile.Open(DownloadedStream, zmRead);
  ZipFile.Read('myzippedfile', DecompressionStream, LocalHeader);
  try
    MyStream.CopyFrom(DecompressionStream, DecompressionStream.Size);
  finally
    DecompressionStream.Free;
  end;
finally
  ZipFile.Free;
end;

请注意,我没有测试过这段代码,我刚刚根据TZipFile的源代码和源代码中包含的文档编写了代码。可能会有一些皱纹,但如果代码表现得像宣传的那样完全符合您的需求。


好的,现在我测试了它,因为我很好奇。这是一个程序,表明这一切都像广告宣传的那样:

program ZipTest;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Classes,
  System.Zip;

procedure ExtractToFile(
  const ZipFileName: string;
  const ZippedFileIndex: Integer;
  const ExtractedFileName: string
);
var
  ZipFile: TZipFile;
  DownloadedStream, DecompressionStream, OutputStream: TStream;
  LocalHeader: TZipHeader;
begin
  DownloadedStream := TFileStream.Create(ZipFileName, fmOpenRead);
  try
    ZipFile := TZipFile.Create;
    try
      ZipFile.Open(DownloadedStream, zmRead);
      ZipFile.Read(ZippedFileIndex, DecompressionStream, LocalHeader);
      try
        OutputStream := TFileStream.Create(ExtractedFileName, fmCreate);
        try
          OutputStream.CopyFrom(DecompressionStream, DecompressionStream.Size);
        finally
          OutputStream.Free;
        end;
      finally
        DecompressionStream.Free;
      end;
    finally
      ZipFile.Free;
    end;
  finally
    DownloadedStream.Free;
  end;
end;

begin
  try
    ExtractToFile('C:\desktop\test.zip', 0, 'C:\desktop\out.txt');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

请注意,我是通过索引而不是文件名提取的,因为这对我来说更方便。我使用文件流而不是内存流,我想你会使用它。但是,由于TZipFile方法适用于TStream,因此我确信代码可以使用任何形式的流。


这是有关ZIP文件的一系列问题中的最新内容。我知道您正在使用XE2,我想知道为什么您似乎不愿意使用XE2提供的内置ZIP类。我没有看到任何迹象表明它不符合您的要求。事实上,正是这种直接使用流的能力使我觉得它对任何应用程序都具有足够的通用性。