數年沒發帖了,上來特別提醒DELPHI用戶注意這個問題。
在呼叫System.ZLib.ZDecompressStream時,某些情況可能陷入死回圈,無法退出。
procedure ZDecompressStream(inStream, outStream: TStream);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: TBytes;
outBuffer: TBytes;
inSize: Integer;
outSize: Integer;
begin
SetLength(inBuffer, BufferSize);
SetLength(outBuffer, BufferSize);
FillChar(zstream, SizeOf(TZStreamRec), 0);
ZDecompressCheck(InflateInit(zstream));
try
inSize := inStream.Read(inBuffer, bufferSize);
while inSize > 0 do
begin
zstream.next_in := @inBuffer[0];
zstream.avail_in := inSize;
repeat
zstream.next_out := @outBuffer[0];
zstream.avail_out := bufferSize;
ZDecompressCheckWithoutBufferError(inflate(zstream, Z_NO_FLUSH));
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
inSize := inStream.Read(inBuffer, bufferSize);
end;
repeat
zstream.next_out := @outBuffer[0];
zstream.avail_out := bufferSize;
zresult := ZDecompressCheckWithoutBufferError(inflate(zstream, Z_FINISH)); <--------------
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);
finally
ZDecompressCheck(inflateEnd(zstream));
end;
end;
function ZDecompressCheckWithoutBufferError(code: Integer): Integer; overload;
begin
Result := code;
if code < 0 then
if (code <> Z_BUF_ERROR) then <------------罪魁禍首
raise EZDecompressionError.Create(string(_z_errmsg[2 - code]));
end;
尚不清楚XE 10.2.3的ZLib代碼為什么在code = Z_BUF_ERROR的時候,不拋出例外。
導致的后果是一直在repeat中死回圈。
uj5u.com熱心網友回復:
再看DELPHI 2010的ZLib庫,完全OK
procedure ZDecompressStream(inStream, outStream: TStream);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: array[0..bufferSize - 1] of AnsiChar;
outBuffer: array[0..bufferSize - 1] of AnsiChar;
inSize: Integer;
outSize: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
ZCompressCheck(InflateInit(zstream));
inSize := inStream.Read(inBuffer, bufferSize);
while inSize > 0 do
begin
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
ZCompressCheck(inflate(zstream, Z_NO_FLUSH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
inSize := inStream.Read(inBuffer, bufferSize);
end;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
zresult := ZCompressCheck(inflate(zstream, Z_FINISH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);
ZCompressCheck(inflateEnd(zstream));
end;
function ZCompressCheck(code: Integer): Integer;
begin
result := code;
if code < 0 then
begin
raise EZCompressionError.Create(_z_errmsg[2 - code]);
end;
end;
function ZDecompressCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
begin
raise EZDecompressionError.Create(_z_errmsg[2 - code]);
end;
end;
uj5u.com熱心網友回復:
也歡迎你貼不同DELPHI版本的ZLib函式代碼出來,看看哪些版本可能存在這個問題。uj5u.com熱心網友回復:
10.2.3編譯的時候有警示資訊嗎?可能有些函式為了跨平臺而修改了,沒測驗。uj5u.com熱心網友回復:
if (code <> Z_BUF_ERROR) then <------------罪魁禍首raise EZDecompressionError.Create(string(_z_errmsg[2 - code]));
上面應當是if code = Z_BUF_ERROR) then
raise EZDecompressionError.Create(string(_z_errmsg[2 - code]));
邏輯上才行得通
uj5u.com熱心網友回復:
Z_BUF_ERROR只是一個警告,而不是一個錯誤,意思是解壓縮后的資料塊的大小超過了緩沖區的大小了,但解壓碩訓能正常進行。你的問題估計是其他原因導致的。
uj5u.com熱心網友回復:
你這估計有點意思啊,我的檔案是損壞了,但是也不能一直在里面死回圈不出來吧。
uj5u.com熱心網友回復:
沒有BUG,ZDecompressCheckWithoutBufferError,就是忽略Z_BUF_ERRORuj5u.com熱心網友回復:
舊版本里面不排除Z_BUF_ERROR這個警告資訊才是BUG。現在Delphi 10.3里面的Indy idCompressorZLib.pas還有這個BUG
uj5u.com熱心網友回復:
QuickReport 5.06 Pro Delphi XE8 這個控制元件在xe8中穩定 嗎?初學者。謝謝!uj5u.com熱心網友回復:
COPY Code Examples 代碼,TZCompressionStream生成的zip,7Z居然說是無效的檔案。
uj5u.com熱心網友回復:
那只是zlib壓縮后輸出的二進制資料,不代表ZIP檔案格式,ZIP除了壓縮演算法之外還有自己的檔案格式(檔案頭),你把zip檔案的檔案頭刪掉看看7zip能不能識別?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/29436.html
標籤:VCL組件開發及應用
上一篇:MATLAB 事實區分樂音與人聲
