[教程]本用 System.Zip 从流中获取解压数据

【前言】

写这个教程的原因,是因为要实现下面的场景:

1、通过 THttpClient 从网络上下载压缩包到内存流中。

2、将内存流中的 ZIP 格式压缩数据中的特定扩展名文件,在内存中直接解压处理,而不是解压到磁盘,再加载。

【实现流程】

1、下载压缩包到内存流中,这个本身直接通过 THttpClient.Get 或 BeginGet 就可以实现,注意 BeginGet 是异步操作,需要在回调中调用 EndAsynHttp 以便触发可能的异常。

var
  AResp: IHttpResponse;
  AStream: TFileStream;
begin
  try
    AResp := FHTTPClient.EndAsyncHTTP(ASyncResult);
    AStream:=AResp.ContentStream;
...

2、IHttpResponse.ContentStream 就是我们需要的内存流对象,下面是真正的代码工作时间:

  • 第一步:需要确定流格式的有效性。System.Zip.TZipFile 类提供了 IsValid 函数来做这一判断。
  • 第二步:将源内存流的位置调整到开始,然后创建 TZipFile 实例,并调用 Open 方法,打开这一内存流。
  • 第三步:通过 TZipFile.FileCount 和 TZipFile.FileNames 属性,来找到内存流中特定扩展名的文件。
  • 第四步:找到文件后,调用 TZipFile.Read 来获取解压后的数据流对象。
  • 第五步:从返回的流中加载数据
if TZipFile.IsValid(AStream) then
    begin
      AStream.Position := 0;
      AZip := TZipFile.Create;
      AZip.Open(AStream, TZipMode.zmRead);
      for I := 0 to AZip.FileCount - 1 do
        begin
        if LowerCase(ExtractFileExt(AZip.FileNames[I])) = '.json' then
          begin
            AZip.Read(I, AJsonStream, AHeader);
              try
                //这里是实际处理流中数据代码,AJsonStream 不需要预先创建
                AJson.LoadFromStream(AJsonStream);
              finally
                FreeAndNil(AJsonStream);
              end;
            break;
          end;
        end;
    end

分享到: