zlib TypeError:需要类似字节的对象,而不是“str”

问题描述 投票:0回答:2

我使用此代码对文本进行编码和压缩。但它无法正常工作:

Traceback (most recent call last): File "E:\SOUND.py", line 114, in <module>
unhexsring = str(zlib.decompress(unhexsring).encode('utf8'))
TypeError: a bytes-like object is required, not 'str' 

你能帮我吗?

import zlib,gzip

def str2hex(s):
    return binascii.hexlify(bytes(str.encode(s)))


def hex2str(h):
    return binascii.unhexlify(h)

hexstring = input()
if len(hexstring) > 200:
    hexstring = str(zlib.compress(hexstring.encode('utf-8')))
    print(hexstring)
hexstring = str2hex(hexstring)
ph = str(hexstring.decode('utf-8'))
print(ph)

#decompressing text
unhexsring = hex2str(hexstring).decode('utf8')
if 'x' in str(unhexsring):
    print('compressed')
    unhexsring = str(zlib.decompress(unhexsring).encode('utf8'))
print(unhexsring)

此代码不会解压缩 zlib 压缩的文本。

所以编码效果很好。

我的问题是,当我获取编码字符串并压缩它时,我无法解压缩它。 应该如何运作:

1>s = input('some text')
2>if len(s) > 200: s = str(zlib.compress(s.encode('utf-8'))) 
3>encoding it with str2hex()
4>decode it with hex2str()
5>str(zlib.decompress(unhexs).encode('utf8'))  <---------- HERE

我无法正确解压它,因为得到这个:

接下来控制台转储

Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> 
========================= RESTART: E:\SOUND.py =========================
dghlkdushfgkjdsfhglkjhsdfgjhdskfjhgkdsfhgkjdhfgkjsdhfgjkhsdkjfghlkjsdhgkjhsdfjghdksjhgkjsdhgkjhsdfkjghdskfjghkdjghdghlkdushfgkjdsfhglkjhsdfgjhdskfjhgkdsfhgkjdhfgkjsdhfgjkhsdkjfghlkjsdhgkjhsdfjghdksjhgkjsdhgkjhsdfkjghdskfjghkdjghdghlkdushfgkjdsfhglkjhsdfgjhdskfjhgkdsfhgkjdhfgkjsdhfgjkhsdkjfghlkjsdhgkjhsdfjghdksjhgkjsdhgkjhsdfkjghdskfjghkdjghdghlkdushfgkjdsfhglkjhsdfgjhdskfjhgkdsfhgkjdhfgkjsdhfgjkhsdkjfghlkjsdhgkjhsdfjghdksjhgkjsdhgkjhsdfkjghdskfjghkdjgh
b'x\x9c\xed\x8d\xb1\r\xc0@\x08\x03\x97\xb5\xb0e\x7f\x87\xb2\x7f\x9eO\x93\x05\xd2\xa5\x02\x1d>\x0cj\x05W\xab\x18\xa3K\\\xb1\x1aE\x0b\x9d\xb2\x98\x83\xf7\xf5dz\x86\xb3#q\x8d<\x84\x8fc\n\xe9Q^0C\xe7\x13\x15\xcc\xfe7~\xd0x\x03\x88\x05\xbb\x9d'
6227785c7839635c7865645c7838645c7862315c725c786330405c7830385c7830335c7839375c7862355c786230655c7837665c7838375c7862325c7837665c7839654f5c7839335c7830355c7864325c7861355c7830325c7831643e5c7830636a5c783035575c7861625c7831385c7861334b5c5c5c7862315c783161455c7830625c7839645c7862325c7839385c7838335c7866375c786635647a5c7838365c78623323715c7838643c5c7838345c783866635c6e5c786539515e30435c7865375c7831335c7831355c7863635c786665377e5c786430785c7830335c7838385c7830355c7862625c78396427
compressed
Traceback (most recent call last):
  File "E:\SOUND.py", line 114, in <module>
    unhexsring = str(zlib.decompress(unhexsring).encode('utf8'))
TypeError: a bytes-like object is required, not 'str'
python python-3.x zlib
2个回答
9
投票

您在这里看到的异常:

unhexsring = str(zlib.decompress(unhexsring).encode('utf8'))
    TypeError: a bytes-like object is required, not 'str'

被提高,因为

zlib.decompress
期望
bytes
。通过更改可以轻松解决此问题

unhexsring = hex2str(hexstring).decode('utf8')    # -> str

unhexsring = hex2str(hexstring)    # -> bytes

但是这会导致新的错误:

unhexsring = zlib.decompress(unhexsring)
    zlib.error: Error -3 while decompressing data: incorrect header check

这件事的发生是因为这一行:

hexstring = str(zlib.compress(hexstring.encode('utf-8')))

str
实例上调用
bytes
不会将
bytes
转换为
str
,而是将字节的
repr
转换为
str

>>> bs = 'Hello World'.encode('utf-8')
>>> print(repr(bs))
b'Hello World'
>>> s = str(bs)
>>> print(repr(s))
"b'Hello World'"    # <- note the b....

str
转换在压缩数据的前面插入一个“b”,从而破坏了标头。现在让我们将十六进制字符串保留为字节对象

hexstring = zlib.compress(hexstring.encode('utf-8'))

但是现在代码又引发了另一个异常:

return binascii.hexlify(bytes(str.encode(s)))
    TypeError: descriptor 'encode' requires a 'str' object but received a 'bytes'

s
现在是一个
bytes
对象,因此无需尝试转换它(请注意,
str.encode
无论如何都会返回
bytes
,因此即使
bytes
是字符串,
s
调用也是多余的) ).

所以

str2hex
变成了

def str2hex(s):
    return binascii.hexlify(s)

现在又出现了另一个错误:

unhexsring = str(zlib.decompress(unhexsring).encode('utf8'))
    AttributeError: 'bytes' object has no attribute 'encode'

zlib.decompress
的输出是一个
bytes
对象,因此它已经被编码(假设它一开始是一个字符串)。你想解码它以获得
str
:

unhexsring = zlib.decompress(unhexsring).decode('utf8')

这是可以从命令提示符作为脚本运行的代码版本:

import binascii
import random
import string
import zlib


def str2hex(s):
    return binascii.hexlify(s)


def hex2str(h):
    return binascii.unhexlify(h)


def main():
    # I don't want to type 200+ chars to test this :-)
    hexstring = ''.join(random.choices(string.ascii_letters, k=201))
    hexstring = hexstring.encode('utf-8')
    if len(hexstring) > 200:
        hexstring = zlib.compress(hexstring)
    print(f'{hexstring=}')
    hexstring = str2hex(hexstring)
    decoded_hexstring = hexstring.decode('utf-8')
    print(f'{decoded_hexstring=}')

    # decompressing text
    unhexstring = hex2str(hexstring)

    # decompressing text
    unhexstring = hex2str(hexstring)
    # Checking for 'x' in the string isn't a good way to check for # compression. For
    # small data we can just try to see if it can be decompressed. For large data
    # we could inspect the # first byte - see
    # https://stackoverflow.com/q/9050260/5320906
    try:
        unhexstring = zlib.decompress(unhexstring)
        print('compressed')
    except zlib.error:
        # Not compressed, do nothing.
        pass
    print(f'{unhexstring=}')


if __name__ == '__main__':
    main()

0
投票

非常有趣的问题,我认为你应该摆脱这个

hexstring = input()

您的代码的简单示例

>>> s ='Vladimir'
>>> str.encode(s)
b'Vladimir'
>>> bytes(str.encode(s))
b'Vladimir'
>>> binascii.hexlify(bytes(str.encode(s)))
b'566c6164696d6972'
>>> binascii.unhexlify(b'566c6164696d6972')
b'Vladimir'
>>> import zlib,gzip
>>> hexstring = str(zlib.compress(s.encode('utf-8')))
>>> type (hexstring)
<class 'str'>
>>> type (s)
<class 'str'>
© www.soinside.com 2019 - 2024. All rights reserved.