是否有一个 8 位代码页 (CP-####) 来定义每个字节?
Is there an 8-bit code page (CP-####) such that every byte is defined?
我目前正在尝试编写数据压缩算法的代码。我的目标是获取一个文件并读取它,将其转换为等效的二进制文件,然后将其存储到输出文本文件中。
例如:
假设我的 输入 是“Hello World”,
那么我在 输出 中想要的是“0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100”。
这段代码对大多数消息都成功地做到了这一点。但是,我有一个文件,其中包含一个必要的字节信息,即“10000001”。在 CP-1252 中,这映射到一个未定义的字符。
我的代码第 9 行第 51 行是否有一个 8 位代码页可以使用所有 256 个可能的代码来避免此错误?
from datetime import datetime
now = datetime.now()
#makes a file with a unique timestamp in the name
stamp = now.strftime("%H%M%S")
f = open("requests" + str(stamp) + ".txt", "w")
#opens desired input file in read mode
text_file = open("videointxt", mode="r", encoding=None)
^
#read whole file to a string
data = text_file.read()
#takes the message converts it to its binary equivakent, and then writes it to the output file
res = ''.join(format(ord(i), '08b') for i in data)
print(res, file=f)
f.close
您的问题不在于代码页本身。您的问题是您试图将二进制信息解释为字形。在 python3.x 中,字符串是 Unicode。对于 Python 要将数据作为字符串读入,它需要知道值到字形的映射,即编码。如果您只想加载原始数据而不解释它,您可能想要执行字节读取并跳过编码。
- text_file = open("videointxt", mode="r", encoding=None)
+ text_file = open("videointxt", mode="rb")
变量 text_file
现在将是 bytes 类型而不是 string 类型,因此您需要更改与它交互的方式,但这确实意味着您不需要弄乱编码,直到决定如何在屏幕上显示信息。
我个人建议以十六进制而不是二进制显示输出。
请注意磁盘上的文本数据已经是二进制格式。将二进制等同于磁盘存储不会带来任何存储增益。从字符转换为二进制并写入磁盘的操作与开始读取文件时发生的操作相反。
正如@chepner 所说,您的代码生成一个由“0”和“1”字符组成的字符串,这将使总文件大小增加 8 倍。
如果您在 linux 终端工作,您可以自己查看:
# my_script.py
with open('tmp', 'rb') as f:
data = file.read()
print(''.join(format(i, '08b') for i in data))
$ echo -n 'a' > tmp
$ xxd -b tmp
00000000: 01100001 a
$ python my_script.py > tmp
$ xxd -b tmp
00000000: 00110000 00110001 00110001 00110000 00110000 00110000 011000
00000006: 00110000 00110001 01
请注意您是如何将文件大小从 1 个字节扩展到 8 个字节的,因为您没有将 'a' 存储为 1 个字节的数据,而是存储了 8 个字符实例 '0' 和 ' 1'.
是的,至少有一个 single-byte 字符集映射每个字节值:Code page 437
这是可视化二进制数据(例如在十六进制编辑器中)的不错选择。它没有换行符。但是注意,虽然它只列出了00作为控制字符,但是很多API还是会将01-1f和7f之间的字符解释为控制字符,所以谨慎使用。
尽管我不会将它用作存储格式,base64 更适合安全地将二进制数据存储在字符串中。
我目前正在尝试编写数据压缩算法的代码。我的目标是获取一个文件并读取它,将其转换为等效的二进制文件,然后将其存储到输出文本文件中。
例如: 假设我的 输入 是“Hello World”,
那么我在 输出 中想要的是“0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100”。
这段代码对大多数消息都成功地做到了这一点。但是,我有一个文件,其中包含一个必要的字节信息,即“10000001”。在 CP-1252 中,这映射到一个未定义的字符。
我的代码第 9 行第 51 行是否有一个 8 位代码页可以使用所有 256 个可能的代码来避免此错误?
from datetime import datetime
now = datetime.now()
#makes a file with a unique timestamp in the name
stamp = now.strftime("%H%M%S")
f = open("requests" + str(stamp) + ".txt", "w")
#opens desired input file in read mode
text_file = open("videointxt", mode="r", encoding=None)
^
#read whole file to a string
data = text_file.read()
#takes the message converts it to its binary equivakent, and then writes it to the output file
res = ''.join(format(ord(i), '08b') for i in data)
print(res, file=f)
f.close
您的问题不在于代码页本身。您的问题是您试图将二进制信息解释为字形。在 python3.x 中,字符串是 Unicode。对于 Python 要将数据作为字符串读入,它需要知道值到字形的映射,即编码。如果您只想加载原始数据而不解释它,您可能想要执行字节读取并跳过编码。
- text_file = open("videointxt", mode="r", encoding=None)
+ text_file = open("videointxt", mode="rb")
变量 text_file
现在将是 bytes 类型而不是 string 类型,因此您需要更改与它交互的方式,但这确实意味着您不需要弄乱编码,直到决定如何在屏幕上显示信息。
我个人建议以十六进制而不是二进制显示输出。
请注意磁盘上的文本数据已经是二进制格式。将二进制等同于磁盘存储不会带来任何存储增益。从字符转换为二进制并写入磁盘的操作与开始读取文件时发生的操作相反。
正如@chepner 所说,您的代码生成一个由“0”和“1”字符组成的字符串,这将使总文件大小增加 8 倍。
如果您在 linux 终端工作,您可以自己查看:
# my_script.py
with open('tmp', 'rb') as f:
data = file.read()
print(''.join(format(i, '08b') for i in data))
$ echo -n 'a' > tmp
$ xxd -b tmp
00000000: 01100001 a
$ python my_script.py > tmp
$ xxd -b tmp
00000000: 00110000 00110001 00110001 00110000 00110000 00110000 011000
00000006: 00110000 00110001 01
请注意您是如何将文件大小从 1 个字节扩展到 8 个字节的,因为您没有将 'a' 存储为 1 个字节的数据,而是存储了 8 个字符实例 '0' 和 ' 1'.
是的,至少有一个 single-byte 字符集映射每个字节值:Code page 437
这是可视化二进制数据(例如在十六进制编辑器中)的不错选择。它没有换行符。但是注意,虽然它只列出了00作为控制字符,但是很多API还是会将01-1f和7f之间的字符解释为控制字符,所以谨慎使用。
尽管我不会将它用作存储格式,base64 更适合安全地将二进制数据存储在字符串中。