所以,我正在使用Python 3并且正在读取文件并将其作为字节分配给内存中的变量。 然后我将二进制数据转换为字符串:
def to_str(bytes_or_str):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode('utf-8', 'replace')
else:
value = bytes_or_str
return value
我这样做的原因是因为我想用我制作的包含第一个256 chr()的列表来编辑和替换文件中的一些字符
编辑加载的文件变量后,我将文件重写为字节:
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode('utf-8', 'replace')
else:
value = bytes_or_str
return value
只要我只使用ASCII字符,效果很好。 我可以使用latin-1而不是utf-8,它可以使用多达256个字符,但之后 256编码和解码方法被破坏。 Latin-1是单字节,最多256个,我猜它是它工作到但不超过256的原因。 我想使用utf-8,因为它涵盖了更广泛的字符范围,但它失败了我的两种编码/解码方法,如果我使用非ASCII字符,数据会丢失。 我想知道这个问题是否是因为utf-8使用超过chr(128)或其他内容超过一个字节的事实?我想知道是否需要使用类似pack()方法的东西来使用多个字节来隔离字符? 使用此函数,我可以找到UTF-8中字符的字节数:
def utf8len(x):
return len(x.encode('utf-8'))
如果编码中的数据丢失错误是由每个字符多个字节引起的,那么我可以用某种方式使用它吗? 有没有其他想法?谢谢你的帮助。
另外:假设我将此字符'Ω'更改为字节,在python控制台中显示为:b'\ xe2 \ x84 \ xa6'。 如果每个字节的字节数是一组更多的字符,这究竟是如何工作的?当我将字符转换为字节时,Python将其显示为字符而不是0和1?不是字节0和1吗?我不知道Python在这里做了什么。
我制作了这段代码,试图解释它是如何工作的,但我仍然不完全理解:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def string2bits(s=''):
return [bin(ord(x))[2:].zfill(8) for x in s]
def bits2string(b=None):
return ''.join([chr(int(x, 2)) for x in b])
def utf8len(x):
return len(x.encode('utf-8'))
def latin1len(x):
return len(x.encode('latin-1'))
char_num = 255
def_char = chr(char_num)
char = def_char
bit = string2bits(char)
char2 = bits2string(bit)
print ('\nString:')
print (char2)
print( '\nUTF-8 byte Len:')
print(utf8len(char))
# I had to add this next if statement because:
# LATIN-1 can't encode character '\u0100' in position 0: ordinal not in range(256)
if char_num < 256:
print( '\nLatin-1 byte Len:')
print(latin1len(char))
print ('\nList of Bits:')
for x in bit:
print (x)
在上面#注释的代码开头,我可以更改utf-8和latin-1之间的脚本编码,还可以更改char_num变量,看看每个编码中该字符的位串是什么,但是如果latin-1的255以上我得到错误:UnicodeEncodeError:'latin-1'编解码器不能编码位置0的字符'\ u0100':序号不在范围内(256)
如果我使用:
将编码从utf-8硬编码到latin-1#!/usr/bin/env python
# -*- coding: latin-1 -*-
这段代码不应该显示latin-1编码的def_char位吗? Python如何在这里工作?
答案 0 :(得分:0)
我认为问题在于,在jpeg标题中存储的值可以包含任何字节值(例如像素密度,标记长度等)。
https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
在Latin-1中,每个字符都是一个字节,但不是每个字符都定义在0-255之间。
https://en.wikipedia.org/wiki/ISO/IEC_8859-1
但是,UTF-8是一种多字节编码。如果超过127,则第一个字节必须以110(对于2个字节的字符),1110(对于三个字节的字符)和11110(对于四个字节的字符)开始。第二个,第三个和第四个字节必须从10开始......
https://en.wikipedia.org/wiki/UTF-8
因此,如果您读取任意字节,则获取无效字节(序列)的概率很高,您可能通过读取jpeg标头来实现。因此,您可以获得Latin-1的有效字节,而不是UTF-8的有效字节。
答案 1 :(得分:0)
我想我应该更清楚。我在这里找到了答案:
https://stackoverflow.com/questions/3956935/storing-binary-data-in-utf-8-string