如何将字节文件中的“\\”替换为“\”?

2024-10-01 11:22:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我的问题是:我有一个加密的字节文件,如下所示:

[w\x84\x7f@\xc6\xab\xc8

我想用PyCrypto解密,但我发现了一个混乱的bug,如下所示:

此处代码:

^{pr2}$

如果我运行这个,它将抛出一个错误:

ValueError                                Traceback (most recent call last)
<ipython-input-3-4fcf0e8076ca> in <module>()
----> 1 cipher.decrypt(s)

D:\Python\anaconda\lib\site-packages\Crypto\Cipher\blockalgo.py in 
decrypt(self, ciphertext)
    293             return res
    294 
--> 295            return self._cipher.decrypt(ciphertext)
    296 

ValueError: Input strings must be a multiple of 8 in length

我打印s的值:

s =  b'[w\\x84\\x7f@\\xc6\\xab\\xc8'

但这是不对的,我需要的是以下结果:

>>> cipher.decrypt(b'[w\x84\x7f@\xc6\xab\xc8')
b'test aaa'

也就是说,我认为我必须将字节文件中的\\\\替换为\,但是我没有用正确的方法来做。有人知道怎么解决这个问题吗?在


Tags: 文件inselfreturn字节ciphervalueerrordecrypt
2条回答

之所以发生这种情况,是因为文件包含字节字符串的文本表示形式[w\x84\x7f@\xc6\xab\xc8),但实际上不是字节本身。是否正确写入文件:

with open('/tmp/file', 'wb') as f:
    f.write(b'[w\x84\x7f@\xc6\xab\xc8')

这样你就不会有阅读问题了:

^{pr2}$

或者通过ast.literal_eval解释保存在文件中的表示,尽管在这种情况下这是不可取的。在

底线是:始终知道您使用的是什么类型的字符串(unicode)或字节,请记住,当您在控制台中打印字节时,您看到的是表示(类似于\xa0的内容),而不是字节本身,因为有些字节没有可打印的形式。在

文件中没有双反斜杠。当您查看bytes对象的repr时,它显示所有转义的反斜杠,以避免混淆,例如\n(换行符)和{}(一个反斜杠后跟一个n)。在

例如:

>>> s = rb'\x84'
>>> s
b'\\x84'
>>> s[0]
92
>>> chr(s[0])
'\\'

所以,你问的问题不存在。文件中只有一个反斜杠。在


实际的问题是,您不需要四个字节的反斜杠x、8和4,而需要单字节b'\x84',即chr(0x84)。但是这四个字节是你文件中的。在

所以你的bug存在于你用来创建这个文件的任何代码中。不知何故,不是将字节转储到文件中,而是转储了这些字节的反斜杠转义字符串表示形式。修复它的正确位置是在创建文件的代码中。不写损坏的数据总比写损坏的数据好,然后设法找出如何清除它。在

但是如果为时已晚——例如,如果你用那破代码加密了一堆你不再有权访问的明文,现在你需要尝试恢复它,那么这个转换正好是可逆的。你只需要分两步来完成。在


首先,使用反斜杠转义或更通用的unicode转义编解码器解码字节:

^{pr2}$

然后,您可以显式地将每个Unicode字符转换为与相同数字匹配的字节:

>>> bytes(map(ord, s.decode('unicode-escape')))
b'[w\x84\x7f@\xc6\xab\xc8'

…或者,有点老调重弹地依赖Python对拉丁语-1的解释:1

>>> s.decode('unicode-escape').encode('latin-1')
b'[w\x84\x7f@\xc6\xab\xc8'

同样,这些反斜杠实际上并不在字符串中,这正是Python表示bytes的方式。例如,如果把它放在b中,hex(b[2])0x84字节\x84,而不是反斜杠字符的0x5c。在


你的创建代码才是真正的问题:

with open(file,'a') as f:

    f.write(str(encrypt_text).split("b'")[1].split("'")[0])
    f.close()

将字节转换为字符串表示形式,前缀为b,前后加引号,每个不能打印的字节都用反斜杠转义,然后去掉b和引号,然后通过将其写入文本模式文件将整个内容编码为UTF-8。在

您只需以二进制模式打开文件并将字节写入其中:

with open(file, 'ab') as f:
    f.write(encrypt_text)

(另外,您不想调用f.close()with语句已经处理好了。)

然后您可以以二进制模式读取文件,并按原样对字节进行解密。在

(或者,如果您真的希望文件是人工可编辑的或其他的,那么您希望选择一种设计为可人工编辑且易于恢复的格式,例如hexlify或{},而不是“Python如何表示bytes用于调试的对象”。)


1。对于拉丁语-1中的所有字符,Unicode保证与Latin-1对齐。Python解释这意味着拉丁语-1应该将0-255之间的每个字节编码为0-255,而不仅仅是ISO-8859-1中实际定义的那些。这是有效的,因为ISO-8859-1没有说明如何处理它没有定义的字节,但并不是每个工具都会同意Python。

相关问题 更多 >