Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 字符串压缩:输出字母表限制为字母数字字符_Python_String_Compression - Fatal编程技术网

Python 字符串压缩:输出字母表限制为字母数字字符

Python 字符串压缩:输出字母表限制为字母数字字符,python,string,compression,Python,String,Compression,我有一个长字符串,我想将其压缩为一个新字符串,限制输出的字母表只包含[a-z][a-z]和[0-9]字符 如何做到这一点,特别是在Python中?虽然许多编码算法可以采用任意的输出范围,但大多数实现不能,而且如果输出范围不是2/16/256的幂,许多算法的效率要低得多 所以,您希望将其分为两部分:首先将一个字节流压缩到另一个字节流。然后将输出字节流编码为字母数字字符。(如果您从非字节流的内容开始,如Python 3字符串或Python 2unicode,则需要将其编码为字节流的第0步。) 例如,

我有一个长字符串,我想将其压缩为一个新字符串,限制输出的字母表只包含
[a-z]
[a-z]
[0-9]
字符


如何做到这一点,特别是在Python中?

虽然许多编码算法可以采用任意的输出范围,但大多数实现不能,而且如果输出范围不是2/16/256的幂,许多算法的效率要低得多

所以,您希望将其分为两部分:首先将一个字节流压缩到另一个字节流。然后将输出字节流编码为字母数字字符。(如果您从非字节流的内容开始,如Python 3字符串或Python 2
unicode
,则需要将其编码为字节流的第0步。)

例如,如果您想要base64,可以执行以下操作:

import base64, zlib
compressed_bytes = zlib.compress(plain_bytes)
compressed_text = base64.b64encode(compressed_bytes)

不幸的是,您不需要base-64,因为它包含一些非字母数字字符

您可以使用,它只有大写字母和6位数字,对代码的唯一更改是
b32encode
,而不是
encode
。但这有点浪费,因为它只使用了8位中的5位,而理论上可以使用8位中的5.594位

如果您希望以最佳方式实现这一点,并且不能仅满足字母数字字符的要求,那么base62是非常复杂的,因为您无法逐字节执行,而只能一次执行7936字节的块。这不会有意思,也不会有效率。您可以通过分块(例如,一次32个字节)并浪费剩余的位来合理地接近最优。但最好使用base64加上转义机制来处理不适合方案的两个字符。例如:

def b62encode(plain):
    b64 = base64.b64encode(plain)
    return b64.replace('0', '00').replace('+', '01').replace('/', '02')

def b62decode(data):
     b64 = '0'.join(part.replace('01', '+').replace('02', '/') 
                    for part in data.split('00'))
     return base64.b64decode(b64)
为了进行比较,以下是每种算法扩展二进制数据的程度:

  • 基数32:60.0%
  • 假基数62:39.2%
  • 实际基数62:~38%
  • 最佳基数62:34.4%
  • 基数64:33%
像base64这样的部分字节传输编码的要点是它们非常简单,运行速度很快。虽然您可以将其扩展到部分位编码,如base62,但您将失去所有优势…因此,如果伪base62不够好,我建议使用完全不同的编码


若要反转此步骤,请按相反顺序反转所有相同步骤

将它们放在一起,使用伪base62,并使用
unicode
/Python 3字符串:

plain_bytes = plain_text.encode('utf-8')
compressed_bytes = zlib.compress(plain_bytes)
b62_bytes = b62encode(compressed_bytes)
b62_text = b62_bytes.decode('ascii')

b62_bytes = b62_text.encode('ascii')
compressed_bytes = b62decode(b62_bytes)
plain_bytes = zlib.decompress(compressed_bytes)
plain_text = plain_bytes.decode('utf-8')

这是非常复杂的。

虽然许多编码算法可以采用任意的输出范围,但大多数实现不能,如果输出范围不是2/16/256的幂,许多算法的效率要低得多

所以,您希望将其分为两部分:首先将一个字节流压缩到另一个字节流。然后将输出字节流编码为字母数字字符。(如果您从非字节流的内容开始,如Python 3字符串或Python 2
unicode
,则需要将其编码为字节流的第0步。)

例如,如果您想要base64,可以执行以下操作:

import base64, zlib
compressed_bytes = zlib.compress(plain_bytes)
compressed_text = base64.b64encode(compressed_bytes)

不幸的是,您不需要base-64,因为它包含一些非字母数字字符

您可以使用,它只有大写字母和6位数字,对代码的唯一更改是
b32encode
,而不是
encode
。但这有点浪费,因为它只使用了8位中的5位,而理论上可以使用8位中的5.594位

如果您希望以最佳方式实现这一点,并且不能仅满足字母数字字符的要求,那么base62是非常复杂的,因为您无法逐字节执行,而只能一次执行7936字节的块。这不会有意思,也不会有效率。您可以通过分块(例如,一次32个字节)并浪费剩余的位来合理地接近最优。但最好使用base64加上转义机制来处理不适合方案的两个字符。例如:

def b62encode(plain):
    b64 = base64.b64encode(plain)
    return b64.replace('0', '00').replace('+', '01').replace('/', '02')

def b62decode(data):
     b64 = '0'.join(part.replace('01', '+').replace('02', '/') 
                    for part in data.split('00'))
     return base64.b64decode(b64)
为了进行比较,以下是每种算法扩展二进制数据的程度:

  • 基数32:60.0%
  • 假基数62:39.2%
  • 实际基数62:~38%
  • 最佳基数62:34.4%
  • 基数64:33%
像base64这样的部分字节传输编码的要点是它们非常简单,运行速度很快。虽然您可以将其扩展到部分位编码,如base62,但您将失去所有优势…因此,如果伪base62不够好,我建议使用完全不同的编码


若要反转此步骤,请按相反顺序反转所有相同步骤

将它们放在一起,使用伪base62,并使用
unicode
/Python 3字符串:

plain_bytes = plain_text.encode('utf-8')
compressed_bytes = zlib.compress(plain_bytes)
b62_bytes = b62encode(compressed_bytes)
b62_text = b62_bytes.decode('ascii')

b62_bytes = b62_text.encode('ascii')
compressed_bytes = b62decode(b62_bytes)
plain_bytes = zlib.decompress(compressed_bytes)
plain_text = plain_bytes.decode('utf-8')

这是非常复杂的。

有一种比base 62或base 64的修改更简单的编码方案,用于将输出限制为62个值。将您的输入作为一个位流(实际上是这样),然后将五位或六位编码为每个输出字符。如果五位是00000或00001,则将其编码为62集的前两个字符。否则,再取一位,给出60个可能的值。用剩下的60个字符来表示这些。继续使用剩余的位。最后用零位填充,得到最后的五位或六位

解码更简单。您只需为接收到的每个字符发射五或六位。您会在末尾丢弃任何不构成完整字节的额外位


此方案产生的扩展为35%,接近理论最优值34.36%。

有一种比base 62或base 64的修改更简单的编码方案,用于将输出限制为62个值。将您的输入作为一个位流(实际上是这样),然后将五位或六位编码为每个输出字符。如果五位为00000或00001,则进行编码