0

我有大量以 lz4 格式压缩的推文数据。我想打开每个文件并解压缩,然后从 python 中提取一些信息。

当我lz4c -d在 Ubuntu 中使用命令解压缩文件时,文件解压缩得很好。但是当我lz4.loads('path_to_file')在 python 中使用时,它会抱怨ValueError: corrupt input at byte 6. 当我尝试以字节模式读取()文件时,会发生相同的错误消息。我该怎么办?

4

4 回答 4

1

python-lz4 包包含 LZ4 库的块和框架 API 的绑定。不推荐使用的loads方法用于读取 LZ4 压缩数据的原始块。这可能不是您想要做的 - LZ4 文件将使用帧格式进行压缩。

从 0.19.1 版开始,python lz4 包完全支持读取带有缓冲的 LZ4 压缩文件,如下所示:

import lz4.frame
chunk_size = 128 * 1024 * 1024
with lz4.frame.open('mybigfile.lz4', 'r') as file:
    chunk = file.read(size=chunk_size)
    # Do stuff with this chunk of data.

它允许您读取文件并分块处理它。这样就无需将整个文件保存在内存中,或者将整个文件解压缩到磁盘。另一方面,如果您确实想将完整文件吞入其中,只需size在上面的调用中保持未指定即可.read()

更多信息可以在文档中找到。

另外:我是 python lz4 绑定的维护者,所以如果你遇到问题,或者文档不清楚,请在项目页面提交问题。

于 2018-01-21T15:21:34.257 回答
1

要么在压缩数据前加上未压缩数据的大小,要么尝试升级到更高版本的 python-lz4 包,它有更好的方式来指定未压缩数据的大小。

无论哪种方式,您都需要预先知道未压缩数据的大小。

请注意,如果您只是解压缩刚刚压缩的内容,它会正常工作,因为压缩器会在压缩数据前加上其未压缩大小。

请继续阅读以了解我的特定案例的详细信息...

我正在使用 Ubuntu 16.04.1LTS,发现使用标准 python-lz4 包或使用标准 pip 导入都没有 python lz4 包的合理工作版本。

我说是明智的,因为这些版本中的解压缩方法需要解压缩消息的确切大小,并且需要为实际数据添加前缀:

Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import lz4
>>> x = '\xb3\x1a\x00\x10\x005\x08\x00\x00\x00\x00\xff\x01\x00\x80\xf7\xae\xe9\x8fP\x8b\xa5\x14\x1a\x00\x196\x1a\x00\x80\x19\xbd\xe9\x8fP\x8b\xa5\x14'
>>> from struct import *
>>> len(x)
38
>>> # Guess 50 for the size of the uncompressed string ??
... 
>>> block = pack('<I', 50) + x
>>> y = lz4.decompress(block)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: corrupt input at byte 31
>>> # Try a bigger value
...
>>> block = pack('<I', 8192) + x
>>> y = lz4.decompress(block)
>>> len(y)
8192

但是现在 lz4.decompress 总是返回我猜测的大小,这意味着我无法确定解压缩数据的实际大小。

我求助于从https://github.com/python-lz4/python-lz4克隆 python-lz4 ,构建然后使用生成的 python 包。这给了我一个改进

enter codePython 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import lz4
>>> x = '\xb3\x1a\x00\x10\x005\x08\x00\x00\x00\x00\xff\x01\x00\x80\xf7\xae\xe9\x8fP\x8b\xa5\x14\x1a\x00\x196\x1a\x00\x80\x19\xbd\xe9\x8fP\x8b\xa5\x14'
>>> # I know that the decompressed data will never be greater then 8192 bytes
...
>>> lz4.block.decompress(x, 8192)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Decompressor wrote 52 bytes, but 8192 bytes expected from header
>>> # Now I know the size required, albeit not programmatically, so ...
...
>>> lz4.block.decompress(x, 52)
'\x1a\x00\x10\x005\x08\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xf7\xae\xe9\x8fP\x8b\xa5\x14\x1a\x00\x10\x006\x08\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x19\xbd\xe9\x8fP\x8b\xa5\x14'

所以这个包的最新版本将未压缩数据的大小作为参数,它可以告诉我实际大小,但只能在异常消息中。

从底层看,从 python-lz4 库对 lz4 C 库的调用实际上是成功的,当你给它一个大于必要的解压缩大小但 python-lz4 选择在两者不匹配时抛出异常。

我不知道该决定背后的背景,但就我而言,当我不知道预先解压缩的数据大小时,这还不是完全有用的。

于 2017-03-01T04:53:13.183 回答
0

尝试使用 lz4tools 包:https ://pypi.python.org/pypi/lz4tools

我的测试失败了lz4

>>> lz4.loads(open("test.js.lz4","rb").read())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: corrupt input at byte 10

但适用于lz4tools

>>> lz4tools.open("test.js.lz4").read()
'[{\n    "cc_emails": [],\n    "fwd_emails": [],\n    "reply_cc_emails": [],\n    "fr_escalated": false,\n    "spam": false,\n    "emai.....
于 2016-10-02T20:26:32.327 回答
0

lz4.loads()解压缩您传递给它的字符串,而不是该字符串中的文件路径。这个库似乎不支持打开文件,所以你必须自己读取数据。

lz4.loads(open('path_to_file', 'rb').read())
于 2016-10-02T20:06:49.330 回答