Delphi:从流中打开一个zip存档->提取到流 [英] Delphi: open a zip archive from a stream -> extract to a stream

查看:429
本文介绍了Delphi:从流中打开一个zip存档->提取到流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Are there any zip components with such features? I need to download a zip archive from the Internet to a stream, then to open the archive from the stream and then to extract files to another stream.

例如 ZipForge 可以从流ZipForge.OpenArchive(MyStream, false);中打开档案 但是如何提取到另一个...?

E.g. ZipForge can open an archive from a stream ZipForge.OpenArchive(MyStream, false); but how to extract to another one...?

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

说明

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

Use ExtractToStream to decompress data stored in the file inside the archive to a TStream descendant object like TFileStream, TMemoryStream or TBlobStream.

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

The FileName parameter specifies file name being extracted.

如果不支持提取,OpenArchive(MyStream, false)方法有什么用...

And what use of the OpenArchive(MyStream, false) method if extraction isn't supported...

推荐答案

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

The zip file component that is built into XE2 will do this.

有一个重载的Open方法,该方法接收TStream作为其输入参数.

There is an overloaded Open method that receives a TStream as its input parameters.

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

To extract individual files you can call an overloaded Read method passing the name of the file that you wish to extract. The extracted file is returned as a new instance of TStream. You can that use CopyFrom on that instance to transfer the extracted file to your stream.

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的源代码和该源代码中包含的文档编写了该代码.可能会有一些折痕,但是如果代码的行为与所宣传的一样,则可以完全满足您的需求.

Note that I've not tested this code, I've just written it based on the source code for TZipFile and the documentation contained in that source code. There may be a few wrinkles in this but if the code behaves as advertised it meets your needs perfectly.

好的,现在我进行了测试,因为我很好奇.这是表明这一切如广告所示的程序:

OK, now I tested it because I was curious. Here's the program that shows that this all works as advertised:

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一起使用,所以我确定代码可以与任何形式的流一起使用.

Note that I extracted by index rather than file name since that was more convenient for me. And I used file streams rather than memory streams which I imagine you would use. However, since the TZipFile methods work with TStream I'm sure that the code will work with streams of any form.

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

This is the latest in a series of questions about ZIP files. I know that you are using XE2 and I wonder why you seem reluctant to use the built in ZIP class that XE2 provides. I've not seen anything to indicate that it will not fulfil your requirements. In fact, it is precisely this ability to work directly with streams that makes me feel it has sufficient generality for any application.

这篇关于Delphi:从流中打开一个zip存档->提取到流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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