1

我想解压缩二进制数据中的 LZ4 原始流。我阅读了文档并提出了以下功能。根据代码,它应该继续解压缩,直到用完压缩数据,但事实并非如此。我究竟做错了什么?另外,我想为压缩大小添加一个 writeln。

function Try(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  k := 0;   
  while True do
  begin
    orig_buff := allocmem(100);
    compressed_buff := allocmem(4064);
    j := inStream.Read(orig_buff^, 100);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff, j, 4064);
    Freemem(orig_buff);
    Freemem(compressed_buff);
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  LZ4_freeStreamDecode(lz4StreamDecode);    
end;

编辑1:删除了释放输出缓冲区(临时缓冲区)的部分,问题仍然存在,而不是解压缩整个流然后退出,它只是事先退出循环。

function Try(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  compressed_buff := allocmem(64 * 1024 * 1024);
  k := 0;   
  while True do
  begin
    orig_buff := allocmem(100);
    j := inStream.Read(orig_buff^, 100);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff, j, (64 * 1024 * 1024));
    Freemem(orig_buff);
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  Freemem(compressed_buff);
  LZ4_freeStreamDecode(lz4StreamDecode);    
end; 
4

1 回答 1

1

LZ4_Decompress_safe_continue 使用“前一个内存块”,因为压缩也依赖于此。您正在破坏该内存块。你不能那样做。相反,您应该使用两个缓冲区并在它们之间切换。您应该在开始之前创建缓冲区,并且只有在解压缩结束时才销毁它们。你说你看过说明书。我不认为你有。它给出了一个明确的例子,并解释了它是如何工作的。

编辑

这就是我将如何修改您的功能。抱歉 - 无法测试

注意我正在使用 2 个缓冲区并在它们之间切换。这是您缺少的一件事

另外我不会使用 Try 作为函数名,它是一个保留字!

function XTry(inStream: TMemorySTream): Boolean;
var
  i, j, k: int64;
  orig_buff: Pansichar;
  compressed_buff1, compressed_buff2: Pansichar;
  lz4StreamDecode: PLZ4_streamDecode_t;
begin
  result := false;
  lz4StreamDecode := LZ4_createStreamDecode();
  orig_buff := allocMem( 128 *1024 );
  compressed_buff1 := allocmem(1024 * 1024);
  compressed_buff2 := allocmem(1024 * 1024);
  k := 0;   
  while True do
  begin
    j := inStream.Read(orig_buff^, 128*1024);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff1, j, 4096);  // <<<< Note 1st buffer
    if i <= 0 then
      break;
    inc(k);
    j := inStream.Read(orig_buff^, 128*1024);
    i := lz4.LZ4_decompress_safe_continue(lz4StreamDecode, orig_buff,
      compressed_buff2, j, 4096);   // Note 2nd buffer
    if i <= 0 then
      break;
    inc(k);
  end;
  if k <> 0 then
    result := True;
  LZ4_freeStreamDecode(lz4StreamDecode);    
  Freemem(compressed_buff1);
  Freemem(compressed_buff2);
  Freemem(orig_buff);

end; 

显然这可以清理很多 - 我只是想尽可能接近您的原始代码

于 2017-03-08T13:45:20.660 回答