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

查看:31
本文介绍了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	est.zip', 0, 'C:desktopout.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天全站免登陆