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