Py学习  »  Python

在Python中将数据压缩成最小的文本量

Allen • 4 年前 • 976 次点击  

def convert_to_ascii85(x):
    p = pickle.dumps(x)
    p = zlib.compress(p)
    return b64.b85encode(p)

我的问题是它生成的字符串比需要的长,因为它只使用字母、数字和符号的子集。如果我能够使用unicode编码,我觉得它可以产生一个较短的字符串,因为它可以访问更多的字符。有办法吗?

我的目标是 不是最小数量的数据/信息/字节 . 我的目标是最少的字符数 . 原因是我发送数据的通道是由字符(精确地说是100k)而不是字节(奇怪,我知道)。我已经测试过可以发送100k个unicode字符,只是不知道如何将字节转换成unicode。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/55221
 
976 次点击  
文章 [ 1 ]  |  最新文章 4 年前
Steve
Reply   •   1 楼
Steve    4 年前

更新:我刚刚看到你改变了你的问题,澄清你关心的是字符长度而不是字节长度。这是一个非常奇怪的约束。我以前从没听说过。我不知道该怎么办。但如果这是你的需要,你想要可预测的阻塞行为,那么我认为你的问题很简单。只需选择可以表示最可能唯一字符的兼容字符编码,然后将二进制文件的块映射到该字符集上,使每个块都是它所能达到的最长的,并且所包含的比特数少于字符编码中可表示的字符数。然后,每个这样的块变成一个字符。因为这个约束有点奇怪,所以我不知道是否有库可以这样做。

更新2:出于对上述内容的好奇,我在谷歌上找到了这个: https://qntm.org/unicodings . 如果你的工具和沟通渠道能够处理UFT-16或UTF-32,那么你可能会在寻求使用它的时候有所收获。如果是这样的话,我希望这篇文章能为您提供您正在寻找的解决方案。我认为本文仍然在针对字节长度和字符长度进行优化,因此这可能无法提供最佳解决方案,但它只能提供帮助(每个字符32个潜在位,而不是7或8)。我找不到任何寻求优化字符计数单独,但也许UTF-32方案,如Base65536是你的答案。退房 https://github.com/qntm/base65536 .

如果你关心的是字节长度,并且你想坚持使用通常所说的“可打印字符”或“纯可打印文本”,那么这里是我最初的答案。。。

Base85非常接近将任意二进制编码为“纯文本”时的最佳效果,如果您希望“纯文本”编码能够在逻辑上分解为有意义的、可预测的块,则它是最佳效果。理论上,您可以使用在高ASCII范围内使用可打印字符的字符集,但经验表明,许多工具和通信通道如果不能处理直接二进制字符,则不能很好地处理高ASCII。尝试每4个二进制字节使用额外的5位,或者使用256位高ASCII而不是128位ASCII,不会节省太多额外的空间。

对于任何BaseXX编码,该算法接受传入的二进制位,并使用它可以使用的XX个可打印字符对它们进行尽可能紧密的编码。Base85将比Base64更紧凑,因为它使用的可打印字符(85)比Base64使用的可打印字符(64个字符)多。

结果是,85个字符是你需要编码4个字节,正好5个可打印字符。许多人会选择增加大约10%的额外长度,以获得这样一个事实,即每4个编码字节将导致正好5个ASCII字符。这只是一个25%的通货膨胀的大小二进制。这对它省下的所有头痛来说一点也不坏。因此,Base85背后的动机。

Base64用于生成更长但问题更少的编码。不使用给各种文本文档(如HTML、XML、JSON等)带来麻烦的字符。这样,Base64在几乎任何上下文中都是有用的,而无需任何转义。你必须更加小心使用Base85,因为它不会抛出这些有问题的字符。为了提高编码/解码效率,它使用范围33(!)通过117(u),从33开始,而不是32,只是为了避免经常出现问题的空格字符。上面不使用的“u”字没什么特别的。

这就是二进制编码方面的故事。另一个问题是,在将二进制表示编码为ASCII之前,您可以做些什么来减小所表示内容的大小。你选择使用 pickle.dumps() zlib.compress() . 如果这些是你最好的选择,那就留给另一个讨论吧。。。