Zipファイルから無圧縮ファイルをStreamに展開するには?

解決


Alpha  2014-02-12 06:01:38  No: 46022

初めまして。
XE4+FMXでTZipfileを使い、Zipファイルから特定ファイルをTStreamへ
展開できないか試しています。

Extractでファイル名を指定して直接ファイル書き出しは出来ますが、
Readを使ってStreamに書き出す際に不具合が発生します。

コードとしては
var
  LStream     : TStream;
  LZipFile    : TZipFile;
  LocalHeader : TZipHeader;
  MemoryStream: TMemoryStream;
begin

  LZipFile := TZipFile.Create;
  LZipFile.Open( 'TestZip.zip' , zmRead);

  LStream      := TStream.Create;
  LZipFile.Read('data.bin', LStream, LocalHeader);

  MemoryStream := TMemoryStream.Create;
  MemoryStream.CopyFrom( LStream, 0 );
  MemoryStream.SaveToFile( 'ExtractData.bin' );
  MemoryStream.Free;

  LZipFile.Free;

end;

取り出したいファイルの圧縮方法が、
"Deflate" の場合:正常に指定ファイルを書き出す。
"Stored (無圧縮)" の場合:Zipファイル全体を書き出す。
ようです。

こういった場合、圧縮方法をチェックし、Storedだった場合は別途処理を
行う必要があるのでしょうか?


monaa  2014-02-13 09:10:58  No: 46023

ソースを全部チェックしたわけでは無いのでなんとも言えませんし、
圧縮ソフトによる違いがあるかもしれませんが
Lhaplusの無圧縮zipからのストリームへの読み込み動作は確認しました。
XE2+VCL
TFeZipFile = class(TZipFileEx)<-DekoさんのHP参照です。
procedure TFeZipFile.GetStream(aStream: TStream; aIndex: Integer);
var
  aInStream:TMemoryStream;
  aLH:TZipHeader;
begin
  aInStream := TMemoryStream.Create;
  Read(aIndex,TStream(aInStream),aLH);
  aStream.CopyFrom(aInStream, FileInfo[aIndex].UncompressedSize);
  aInStream.Free;
end;


Alpha  2014-02-14 11:38:11  No: 46024

>>monaaさん
検証ありがとうございます。
こちらでも試してみた結果、無圧縮時のファイルサイズをLocalHeaderから
無圧縮時のファイルサイズを取得しCopyFromで同じ値を設定すれば、
元のコードでもうまくいきました。

圧縮ファイルの場合はCopyFromで0を指定してもうまくいっていたので、
そのままいけるのかと思っていました。
もちょっと検証すればよかったですね…


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加