我有一些数据(主要是一系列的numpy数组),我想将其转换为可以复制/粘贴/通过电子邮件发送的文本。我创建了执行此操作的以下公式。
import tkinter as tk
import numpy as np
root = tk.Tk()
var = 4.5
var = np.round(var)
Label = tk.Label(root, text = 'hello world!')
Label.pack()
root.mainloop()
我的问题是它产生的字符串比需要的更长,因为它仅使用字母,数字和符号的子集。如果我能够使用unicode进行编码,我觉得它可以产生较短的字符串,因为它可以访问更多字符。有办法吗?
编辑以澄清: 我的目标是不要最少的数据/信息/字节。 我的目标是最少的字符数。原因是我通过其发送数据的通道是用字符(准确地说是100k)而不是字节(奇怪,我知道)限制的。我已经测试过可以发送10万个Unicode字符,但我不知道如何将字节转换为Unicode。
答案 0 :(得分:4)
更新:我刚刚看到您更改了问题,以澄清您关心的是字符长度而不是字节长度。这是一个非常奇怪的约束。我以前从未听说过。我不知道该怎么做。但是,如果这是您的需要,并且想要可预测的阻止行为,那么我认为您的问题非常简单。只需选择可以表示最多可能的唯一字符的兼容字符编码,然后在该字符集上映射二进制文件的块,以使每个块是最长的块,但其位数少于您的可表示字符的数目字符编码。每个这样的块然后成为单个字符。由于这种约束有点奇怪,所以我不知道是否有图书馆可以做到这一点。
UPDATE2:我对以上内容感到好奇,我只是Google搜索并发现了这个内容:https://qntm.org/unicodings。如果您的工具和通讯渠道可以处理UFT-16或UTF-32,那么您可能会寻求使用它。如果是这样,我希望本文能为您提供所需的解决方案。我认为本文仍在针对字节长度与字符长度进行优化,因此也许这将无法提供最佳解决方案,但只能提供帮助(每个字符32个潜在位,而不是7或8)。我找不到任何试图在字符数上进行优化的东西,但是也许像Base65536这样的UTF-32方案是您的答案。检出https://github.com/qntm/base65536。
如果您关心的是字节长度,并且想要坚持使用通常所说的“可打印字符”或“普通可打印文本”,那么这就是我的原始答案...
除了Base85以外,还有一些选项可以从编码中获得更好的“可读文本”编码空间效率。还需要放弃更多空间效率并选择Base64。在这里,我将同时使用Base85和Base64。如果您可以使用Base85,那么二进制文件的膨胀率只会受到25%的打击,这样做可以省去很多麻烦。
Base85非常接近您尝试将任意二进制编码为“纯文本”时要执行的最佳操作,如果您希望逻辑上可以“纯文本”编码,则它是您可以做到的最佳操作分成有意义的,可预测的块。从理论上讲,您可以使用在高ASCII范围内使用可打印字符的字符集,但是经验表明,如果许多工具和通讯通道无法处理直接二进制,则它们不能很好地处理高ASCII。尝试使用每4个二进制字节额外的5位空间不会节省太多额外的空间,因此使用256位高ASCII与128位ASCII可能会使用这些空间。
对于任何BaseXX编码,该算法都会采用传入的二进制位,并使用其可使用的XX个可打印字符对它们进行尽可能严格的编码。 Base85将比Base64紧凑,因为它使用的打印字符(85)比Base64(64个字符)更多。
标准ASCII中有95个可打印字符。因此,存在一个Base95,它是使用所有可打印字符的最紧凑的编码。但是,尝试使用所有95位都是混乱的,因为这会导致传入位的阻塞不均匀。每4个二进制字节映射到少于5个字符的小数部分。
原来,您需要85个字符才能将4个字节编码为正好5个可打印字符。许多人会选择增加大约10%的额外长度,以达到每4个编码字节导致准确5个ASCII字符的事实。这只是二进制文件大小的25%膨胀。对于它所节省的所有头痛,这根本不是一件坏事。因此,Base85背后的动机。
Base64用于生成更长但问题更少的编码。不使用对各种文本文档造成麻烦的字符,例如HTML,XML,JSON等。这样,Base64几乎可以在任何上下文中使用,而无需进行任何转义。您必须更加小心使用Base85,因为它不会抛出任何这些有问题的字符。为了提高编码/解码效率,它使用从33(而不是32)开始的范围从33(“!”)到117(“ u”),以避免经常出现问题的空格字符。 'u'上方不使用的字符没什么特别的。
这就是二进制-> ASCII编码方面的故事。另一个问题是在将其二进制表示编码为ASCII之前,您可以采取什么措施来减小所表示内容的大小。您选择使用pickle.dumps()
和zlib.compress()
。如果这些是您最好的选择,请继续讨论...