对大型二进制文件进行排序

对大型二进制文件进行排序

是否有用于对包含固定长度二进制记录的大文件进行排序的 Unix 实用程序?

换句话说,我正在寻找类似 sort(1) 但具有固定长度记录的二进制文件。

我可以将文件转换为文本,然后使用 sort(1) 进行排序,然后转换回二进制表示,但我正在寻找更节省时间和空间的方法。

答案1

事实证明你很幸运;有一个 GNU 风格的 unix 程序可以做到这一点:排序

bsort是一种超高效的就地基数排序实现,在处理大于 RAM 的文件时会仔细注意内存访问模式。我说的高效是指能够超越http://sortbenchmark.org2014 年年中,在硬件上实现了 10^8 的节能排序记录 - 记录为 889 焦耳,其早期原型能够在普通的 MacBook Pro 上以 335 焦耳完成相同的排序。对于完全装入 RAM(三位数兆字节)的“小型”数据集,它比 libc 的 qsort 库快 3 倍左右。

答案2

一种解决方案是将输入文件转换为十六进制,将每个记录编码在单独的行上,对其进行排序,然后转换回二进制:

record_size=32
cat input \
    |xxd -cols $record_size -plain \
    |sort \
    |xxd -cols $record_size -plain -revert

但是速度很慢(xxd 在我的计算机上大约为 40MB/s)

因此,由于我需要它,所以我写了binsort,其作用是:

binsort --size 32 ./input ./output

使用--size 32,它假设 32 字节固定大小的记录,读取./input,将排序后的记录写入./output

答案3

如果您引用相对于第一个“记录”的二进制数据,则 Unix 的排序实用程序可以根据记录内的字节位置对二进制数据进行排序。例如 -k1.28,1.32。

Unix 排序在行尾概念方面不太灵活。根据您的数据,您可能能够执行比 user68497 建议的基于 xxd 的更简单的流编辑,并使用以空结尾的行。不过,这仍然可能涉及大量内存数据复制,并且不会接近基于 mmap 的方法的速度。

但是如果您以某种方式使用 unix 排序,请注意语言环境。排序假定其输入是文本,而语言环境会影响排序顺序。

相关内容