我的目标是能够减少查看特定部分所需的时间,从非常大的日志文件压缩到.xz格式。
例如,如果.xz文件是6GB压缩文件和60 6GB未压缩文件,使用简单的命令(如xzcat <file> | tail -1 )来查看未压缩文件的最后一行,则需要等待许多分钟才能解压整个文件。
通过阅读https://stackoverflow.com/a/34053829/12132601,我的理解是.xz文件被组织成块,如果您能够找到要取的文件的正确起始位置和长度,就可以解压特定的块。然而,我无法理解这一点:
-您可以使用xz -详细-列表FILE.xz获得块偏移量列表。如果您想要最后一个块,您需要它的压缩大小(第5列)加上36个字节的开销(通过比较大小和
hd big.log.sp0.xz |grep 7zXZ找到)。使用尾-c获取该块,并通过xz进行管道。由于上面的问题需要文件的最后一行,所以我将其通过尾-n1进行传输:
SIZE=$(xz -详细
特别是关于36的管理费用以及他是如何得到的。
加上36字节的开销(通过将大小与
hd big.log.sp0.xz |grep 7zXZ进行比较找到)
我一直在读https://tukaani.org/xz/xz-file-format.txt,但是我看不懂。我不知道36是从哪里来的。
36肯定和我的档案不一样。实际上,我试过1到100次,但都没有效果。
我的文件的前3行与hd类似
00000000 fd 37 7a 58 5a 00 00 04 e6 d6 b4 46 04 c0 e2 c3 |.7zXZ......F....|
00000010 39 80 80 80 08 21 01 14 00 00 00 00 3e 0b 39 68 |9....!......>.9h|
00000020 e9 e2 3f f0 00 5d 00 18 8d 82 f9 18 7b b2 75 c6 |..?..]......{.u.|xz -lvv <myxzfile>的前几行如下所示:
<myxzfile> (1/1)
Streams: 1
Blocks: 4,080
Compressed size: 5,789.9 MiB (6,071,150,860 B)
Uncompressed size: 63.7 GiB (68,443,750,160 B)
Ratio: 0.089
Check: CRC64
Stream padding: 0 B
Streams:
Stream Blocks CompOffset UncompOffset CompSize UncompSize Ratio Check Padding
1 4,080 0 0 6,071,150,860 68,443,750,160 0.089 CRC64 0
Blocks:
Stream Block CompOffset UncompOffset TotalSize UncompSize Ratio Check CheckVal Header Flags CompSize MemUsage Filters
1 1 12 0 942,592 16,777,216 0.056 CRC64 e77988a5264b499e 20 cu 942,562 5 MiB --lzma2=dict=4MiB
1 2 942,604 16,777,216 887,748 16,777,216 0.053 CRC64 b1124241f57be325 20 cu 887,718 5 MiB --lzma2=dict=4MiB
1 3 1,830,352 33,554,432 836,008 16,777,216 0.050 CRC64 0b9ed8b7bd1be895 20 cu 835,978 5 MiB --lzma2=dict=4MiB
1 4 2,666,360 50,331,648 893,172 16,777,216 0.053 CRC64 4399327c125c6a13 20 cu 893,144 5 MiB --lzma2=dict=4MiB
1 5 3,559,532 67,108,864 757,964 16,777,216 0.045 CRC64 908e32d2276f5b4b 20 cu 757,933 5 MiB --lzma2=dict=4MiB如果我只想解压缩第三个块,我天真地认为head -c 2666360 2022-06-16T00:00:00.xz | tail -c 836008 | unxz -c会工作,但它当然不能。我应该采取的文件的起始位置和长度是什么,为什么?
发布于 2022-06-18 17:29:18
看起来,我只需要将前12个字节cat到我需要的块上。即
cat <(head -c 12 2022-06-16T00:00:00.xz) <(head -c 2666360 2022-06-16T00:00:00.xz | tail -c 836008) | unxz -c发布于 2022-06-19 16:52:18
在解压缩文件时,默认情况下的unxz (或xz -d)命令尝试自动检测存档的类型(相当于--format=auto)。这适用于xz文件(但在开始时需要xz流头)。
但是,如果您剪切一个xz文件以只取一个块,它就不再是一个有效的xz文件了,因为它错过了xz流头(这是xz文件的前12个字节,假设xz文件只由一个流组成)、xz索引和xz流页脚。
但是,如果在xz文件上取前12个字节,然后追加一个块的字节,则仍然缺少xz索引和xz流页脚,解压缩文件的工具可能支持也可能不支持(*)。看来unxz命令支持得很好,所以这是一种方法!
(*)读取xz文件的主要方法有两种:
流模式中的
xz正在做的事情),缺点是如果您拥有整个文件,就不能随机访问中读取数据。
另一种方法是进一步削减xz块的数据,只获取压缩的数据,然后用unxz -F raw解压缩它。然而,这有两个缺点:
传递给
因此,我想说,这是不切实际的手工操作。
阅读
在那篇文章中,他们不是在xz文件中有一个包含几个块的流,而是创建(然后读取)一个xz文件,该文件由几个流组成,每个流都有一个块。
在这种情况下,使用tail -c获取最后一个流就足够了,因为一个由一个流组成的文件是一个有效的xz文件。
我没有找到任何方法可以轻松地使用xz命令行在xz文件中进行随机访问(也没有找到pixz )。
如果您正在使用Python,那么我将借此机会突出显示我编写的python-xz库,作为lzma的插入替代,以便透明地执行对xz文件的随机访问。
在你的例子中,像这样的事情:
import xz
with xz.open('2022-06-16T00:00:00.xz') as f:
f.seek(33_554_432) # position is decompressed offset
print(f.read(0x1000000))https://stackoverflow.com/questions/72671207
复制相似问题