2012-01-17 53 views
7

是否有任何zip組件具有此類功能?我需要從互聯網上下載一個zip壓縮文件到流中,然後從流中打開壓縮文件,然後將文件解壓到另一個流中。德爾福:從流中打開zip存檔 - >提取到流

E.g. ZipForge可以打開一個檔案流ZipForge.OpenArchive(MyStream, false); 但如何提取到另一個......?

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

說明

使用ExtractToStream解壓縮存儲在文件中的 存檔內像TFileStream的,內存流 或TBlobStream一個T流後裔對象數據。

FileName參數指定正在提取的文件名。

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

回答

19

內置到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類。我還沒有看到任何證據表明它不會滿足您的要求。事實上,正是這種直接與流有關的能力讓我覺得它對任何應用程序都具有足夠的通用性。

+1

非常感謝大衛! – maxfax 2012-01-17 16:33:22

+0

我沒有看到Read方法(我檢查得很快),有關於它的純粹信息http://docwiki.embarcadero.com/VCL/en/System.Zip.TZipFile。閱讀 – maxfax 2012-01-17 16:39:23

+0

@maxfax你有什麼版本的Delphi?我有Pro,並且有源代碼。我對你最近的ZIP問題的答案完全基於閱讀資料來源。我完全不知道ZIP文件,也不知道這個組件。如果你有源代碼,那麼對我來說這將是一個巨大的幫助。 – 2012-01-17 16:45:34