我目前正在学习将Python用于二进制文件。我在正在阅读的书中遇到以下代码:
FILENAME = 'pc_rose_copy.txt'
def display_contents(filename):
fp = open(filename, 'rb')
print(fp.read())
fp.close()
def encrypt(filename):
fp = open(filename, 'r+b')
text = fp.read()
fp.seek(0)
for c in text:
if c <= 128:
fp.write(bytes([c+128]))
else:
fp.write(bytes([c-128]))
fp.close()
display_contents(FILENAME)
encrypt(FILENAME)
display_contents(FILENAME)
我对此代码有一些疑问,我在书中找不到答案:
1)在第13行(“ if c <= 128”)中,由于文件是以二进制模式打开的,因此每个字符都将作为其在ASCII表中的索引被读取(即,等同于'if ord(c )<= 128'文件不是处于二进制模式吗?
2)如果是,那么检查任何字符的索引是否高于128有什么意义,因为这是一个.txt文件,其中包含罗密欧与朱丽叶的一段文字?
3)这一点更多是出于好奇,所以请原谅天真。我知道这在这种情况下不适用,但是说脚本遇到一个字节值为128的'c',因此将其添加128。 256字节是什么样子-是11111111 00000001吗?
答案 0 :(得分:2)
真正发生的是该脚本切换了每个字节的最高有效位。等效于每个字节加减128。您可以通过在运行脚本之前/之后查看文件内容来查看此内容(Linux或Mac上的xxd -b file.txt
可以让您看到确切的位/字节)。
下面是一些示例文本:
之前的文件内容:
11110000 10011111 10011000 10000100 00001010
之后的文件内容:
01110000 00011111 00011000 00000100 10001010
运行脚本两次(或任何偶数次)可以通过将所有高位切换回原始值来恢复原始文本。
问题/解答:
1)如果文件是ASCII编码的,则为是。例如对于文件abc\n
,c
的值为97、98、99和10(换行符)。您可以通过在循环中添加print(c)
来验证这一点。此脚本也可以在非ASCII编码的文件上运行*(上面的示例是UTF-8)。
2)这样我们就可以翻转位。即使我们仅处理ASCII文件(不保证),但由于我们已将每个字节添加128,因此从加密 ASCII文件获得的字节将大于128。因此,我们仍然需要处理这种情况才能解密自己的文件。
3)照原样,脚本崩溃,因为bytes()
要求的值在0 <= x < 256
范围内(请参阅documentation)。您可以创建一个使用echo -n -e '\x80\x80\x80' > 128.txt
来中断脚本的文件。该脚本应该使用<
来正确处理这种情况。
* 3除外)
答案 1 :(得分:1)
我认为加密功能也应该是解密功能。
加密从文本文件变为只有高字节的二进制文件。但是else子句用于从高字节返回到文本。我认为,如果您添加了额外的encrypt(FILENAME)
,您将获得原始文件。
'c'在文本文件中不能真正为128。最高值为126(〜),127为del
“字符”。但是c = 128并加上128作为字节将在我们对256进行模运算时为0(环绕)。在C中,情况就是这样(对于无符号字符)。