解压缩未知大小的LZ4流

时间:2017-03-08 13:00:13

标签: delphi lz4

我想在二进制数据中解压缩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; 

1 个答案:

答案 0 :(得分: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; 

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