使用 Perl 解压缩 LZ4 blob
Uncompressing a LZ4 blob with Perl
我在 SQLite 数据库中有一个 table,用于存储使用 LZ4 算法压缩的 blob。我正在尝试使用 Compress::LZ4 中的 decompress/uncompress 函数,但没有取得任何成功。
示例 SQLite 数据库可以是 downloaded from here。
以下是我如何连接到 SQLite 数据库并获取 blob:
use DBI;
use Data::Dump;
use MIME::Base64;
use Compress::LZ4;
my $dbh = DBI->connect("dbi:SQLite:dbname=$ARGV[0]","","");
$sth = $dbh->prepare("select blob_data from blob_parts where data_fk = 6");
$sth->execute();
$result = $sth->fetch;
$blob = $result->[0];
dd $blob;
dd (decompress($blob));
$sth->finish();
$dbh->disconnect;
对于我在此示例代码中选择的特定 blob (data_fk=6),dd 输出以下内容:
"LZ4>[=12=][=12=]\xF7\xD6df\xF1mBXML\xA1\aVersion\xA1Type\xA1Id\xA1Ref\xA1Size\xA1use\xA1expr\xA1value\xA1data\xA1/Serialization\xA1\aPoints3\xA1\tuser_
E[=12=]\xF0\bvertices\xA1double\xA1\bhas_attr\xA1\n[=12=]\xC7object_ids\xA1\n\f[=12=]\xF1Mitem\xA1\tis_active\xA0~B\n\x8C[=12=][=12=][=12=]\xAA[=12=]\xA4\x82\x88\x80\x82\x82\xA6B\b\x80B
\b\x88B\x93[=12=][=12=][=12=]`\xACu\xCF\xBF[=12=][=12=][=12=][=12=]\xCC\xF8\xC2?[=12=][=12=][=12=][=12=][=12=]\x004\@[=12=][=12=][=12=]
\xAA\xEF\xA9\x001h\xC5\xB1\b[=12=]\xD0[=12=][=12=]$\@B\x85B\x87B
C[=12=]\xF0\aB\"[=12=]\x88B$\x85B\"[=12=]\x88B\ $\x85"
但是 decompress/uncompress 功能只是 return undef。未压缩的数据应该类似于(以下输出由 XML 转换器生成):
<?xml version="1.0" encoding="utf-8"?>
<MultiStreamDocument>
<!-- Stream 1 -->
<?xml version="1.0" encoding="utf-8"?>
<data xmlns="" Id="1" Type="Points3" Version="1 2 0 1 1">
<user_data Size="0"></user_data>
<vertices Size="2">
<double>-0.24577860534191132</double>
<double>0.14821767807006836</double>
<double>20</double>
<double>0.050656620413064957</double>
<double>0.069418430328369141</double>
<double>10</double>
</vertices>
<has_attr>false</has_attr>
<has_object_ids>true</has_object_ids>
<object_ids Size="2">
<item Version="3">
<is_active>false</is_active>
</item>
<item Version="3">
<is_active>false</is_active>
</item>
</object_ids>
</data><!-- Stream size: 126 bytes -->
</MultiStreamDocument>
从此 SQLite 数据库获取未压缩的 blob 数据的正确方法是什么?
您的数据看起来像是经过 LZ4 压缩并以四个字节为前缀 "LZ4"
大概是作为格式指示符
接下来的四个字节 ">[=13=][=13=]"
是小端原始大小字段,计算结果为 318 字节,这是合理的。 decompress
库函数需要这个字段
所以理论上你应该可以写
$blob = substr($blob(4);
dd decompress($blob);
并得到正确的结果。然而,这对我来说也是 undef
的值,这表明数据以某种方式损坏
可以肯定的是,大部分数据最终都未压缩。长度字段后面的两个字节是"\xF7\xD6"
,表示后面的数据是229字节的字面量数据(第一个字节的高位nybl——0xF——加上第二个字节——0xD6——是0xE5或者229) .所以这部分数据
"df\xF1mBXML\xA1\aVersion\xA1Type\xA1Id\xA1Ref\xA1Size\xA1use\xA1expr\xA1value\xA1data\xA1/http://www.slb.com/Petrel/2011/03/Serialization\xA1\aPoints3\xA1\tuser_E[=11=]\xF0\bvertices\xA1double\xA1\bhas_attr\xA1\n[=11=]\xC7object_ids\xA1\n\f[=11=]\xF1Mitem\xA1\tis_active\xA0~B\n\x8C[=11=][=11=][=11=]\xAA[=11=]\xA4\x82\x88\x80\x82\x82\xA6B\b\x80"
是字面意思,从它包含的可读文本的数量可以猜到
接下来的两个字节,"B"
应指示已翻译缓冲区内的偏移量,应从中复制数据。不幸的是,它的计算结果为 6210,而正如我们所见,缓冲区到目前为止只有 229 字节长。这大概是数据导致 decompress
函数停滞和 return undef
的地方
这是我对您的数据的最大了解。希望对你有帮助
我在 SQLite 数据库中有一个 table,用于存储使用 LZ4 算法压缩的 blob。我正在尝试使用 Compress::LZ4 中的 decompress/uncompress 函数,但没有取得任何成功。
示例 SQLite 数据库可以是 downloaded from here。
以下是我如何连接到 SQLite 数据库并获取 blob:
use DBI;
use Data::Dump;
use MIME::Base64;
use Compress::LZ4;
my $dbh = DBI->connect("dbi:SQLite:dbname=$ARGV[0]","","");
$sth = $dbh->prepare("select blob_data from blob_parts where data_fk = 6");
$sth->execute();
$result = $sth->fetch;
$blob = $result->[0];
dd $blob;
dd (decompress($blob));
$sth->finish();
$dbh->disconnect;
对于我在此示例代码中选择的特定 blob (data_fk=6),dd 输出以下内容:
"LZ4>[=12=][=12=]\xF7\xD6df\xF1mBXML\xA1\aVersion\xA1Type\xA1Id\xA1Ref\xA1Size\xA1use\xA1expr\xA1value\xA1data\xA1/Serialization\xA1\aPoints3\xA1\tuser_ E[=12=]\xF0\bvertices\xA1double\xA1\bhas_attr\xA1\n[=12=]\xC7object_ids\xA1\n\f[=12=]\xF1Mitem\xA1\tis_active\xA0~B\n\x8C[=12=][=12=][=12=]\xAA[=12=]\xA4\x82\x88\x80\x82\x82\xA6B\b\x80B \b\x88B\x93[=12=][=12=][=12=]`\xACu\xCF\xBF[=12=][=12=][=12=][=12=]\xCC\xF8\xC2?[=12=][=12=][=12=][=12=][=12=]\x004\@[=12=][=12=][=12=] \xAA\xEF\xA9\x001h\xC5\xB1\b[=12=]\xD0[=12=][=12=]$\@B\x85B\x87B C[=12=]\xF0\aB\"[=12=]\x88B$\x85B\"[=12=]\x88B\ $\x85"
但是 decompress/uncompress 功能只是 return undef。未压缩的数据应该类似于(以下输出由 XML 转换器生成):
<?xml version="1.0" encoding="utf-8"?>
<MultiStreamDocument>
<!-- Stream 1 -->
<?xml version="1.0" encoding="utf-8"?>
<data xmlns="" Id="1" Type="Points3" Version="1 2 0 1 1">
<user_data Size="0"></user_data>
<vertices Size="2">
<double>-0.24577860534191132</double>
<double>0.14821767807006836</double>
<double>20</double>
<double>0.050656620413064957</double>
<double>0.069418430328369141</double>
<double>10</double>
</vertices>
<has_attr>false</has_attr>
<has_object_ids>true</has_object_ids>
<object_ids Size="2">
<item Version="3">
<is_active>false</is_active>
</item>
<item Version="3">
<is_active>false</is_active>
</item>
</object_ids>
</data><!-- Stream size: 126 bytes -->
</MultiStreamDocument>
从此 SQLite 数据库获取未压缩的 blob 数据的正确方法是什么?
您的数据看起来像是经过 LZ4 压缩并以四个字节为前缀 "LZ4"
大概是作为格式指示符
接下来的四个字节 ">[=13=][=13=]"
是小端原始大小字段,计算结果为 318 字节,这是合理的。 decompress
库函数需要这个字段
所以理论上你应该可以写
$blob = substr($blob(4);
dd decompress($blob);
并得到正确的结果。然而,这对我来说也是 undef
的值,这表明数据以某种方式损坏
可以肯定的是,大部分数据最终都未压缩。长度字段后面的两个字节是"\xF7\xD6"
,表示后面的数据是229字节的字面量数据(第一个字节的高位nybl——0xF——加上第二个字节——0xD6——是0xE5或者229) .所以这部分数据
"df\xF1mBXML\xA1\aVersion\xA1Type\xA1Id\xA1Ref\xA1Size\xA1use\xA1expr\xA1value\xA1data\xA1/http://www.slb.com/Petrel/2011/03/Serialization\xA1\aPoints3\xA1\tuser_E[=11=]\xF0\bvertices\xA1double\xA1\bhas_attr\xA1\n[=11=]\xC7object_ids\xA1\n\f[=11=]\xF1Mitem\xA1\tis_active\xA0~B\n\x8C[=11=][=11=][=11=]\xAA[=11=]\xA4\x82\x88\x80\x82\x82\xA6B\b\x80"
是字面意思,从它包含的可读文本的数量可以猜到
接下来的两个字节,"B"
应指示已翻译缓冲区内的偏移量,应从中复制数据。不幸的是,它的计算结果为 6210,而正如我们所见,缓冲区到目前为止只有 229 字节长。这大概是数据导致 decompress
函数停滞和 return undef
这是我对您的数据的最大了解。希望对你有帮助