首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按位置解压UTF-8编码线

按位置解压UTF-8编码线
EN

Stack Overflow用户
提问于 2021-10-18 19:33:46
回答 3查看 135关注 0票数 0

评论:虽然我理解对数据的“准确性”的一些担忧,但我认为这对这个问题并不重要。数据就是这样的。如果是这样的话,就会对可能的解决方案感兴趣。

-

我需要读取包含unicode字符的文件。这些行包含多个列,每个列从固定位置开始。

下面是一个示例(我已经将连字符用于指示单个列的结尾位置,连字符实际上不是字符串的一部分)。0004-1235957-A CORU¥A -ABC在上面的例子中,第1列占据前4个位置,第2列占据接下来7个位置,第3列占据接下来15个位置,第4列占据接下来3个位置等等。

我使用以下代码来解析这一行:

代码语言:javascript
复制
line = '00041235957A CORU¥A       ABC\n'

formats = ('4s 7s 15s 3s')
st = struct.Struct(formats)
fields = tuple(s.decode() for s in st.unpack_from(line.encode()))
print(fields)

这是我得到的输出:

代码语言:javascript
复制
('0004', '1235957', 'A CORU¥A      ', ' AB')

如果您查看最后一篇专栏文章,它实际上被错误地读取了。原因是,在unicode中,字符“原”占用两个字节,导致只读取前14个字符(和15个字节),从下面的位置读取列4。

我想要的是读取第3列的15个字符,而不是与数据中的编码无关的15个字节。即使我在行上尝试子字符串方法,我也会得到相同的行为。

专家们能否对此提供一些指导?谢谢。

EN

回答 3

Stack Overflow用户

发布于 2021-10-19 01:35:14

当您line.encode()时,默认编码是utf-8。如下面所示,¥符号变成两个字节\xc2\xa5,抛出计数:

代码语言:javascript
复制
>>> line = '00041235957A CORU¥A       ABC\n'
>>> line.encode()
b'00041235957A CORU\xc2\xa5A       ABC\n'

正如评论所提到的,你很可能一开始就误读了这个文件,因为日元符号不太可能出现在看起来像西班牙单词的中间。确保您知道该文件的原始编码是什么,以便正确读取该文件。考虑以二进制格式读取文件,例如open(filename,'rb'),并将所述行的原始字节作为示例发送。

以下是两个“解决办法”:

代码语言:javascript
复制
import struct

line = '00041235957A CORU¥A       ABC\n'

st = struct.Struct('4s7s15s3s')
# encode with a single-byte encoding so the length doesn't change.
fields = tuple(s.decode('latin1') for s in struct.unpack_from(line.encode('latin1')))
print(fields)

# slice the string directly (RECOMMENDED)
fields = line[:4],line[4:11],line[11:26],line[26:29]
print(fields)

输出:

代码语言:javascript
复制
('0004', '1235957', 'A CORU¥A       ', 'ABC')
('0004', '1235957', 'A CORU¥A       ', 'ABC')
票数 2
EN

Stack Overflow用户

发布于 2021-10-19 05:31:07

您是否希望以可读、可重复的方式对行字符进行划分,您可以使用切片对象。

代码语言:javascript
复制
>>> s1 = slice(0, 4)
>>> s2 = slice(4, 11)
>>> s3 = slice(11, 26)
>>> s4 = slice(26, 29)
>>> slices = line[s1], line[s2], line[s3], line[s4]
>>> slices
('0004', '1235957', 'A CORU¥A       ', 'ABC')

切片对象在功能上与从字符串或列表(例如s1 = line[0:4] )中获取一个片段相同,但它们与被切片的序列无关。

正如注释和另一个答复中指出的那样,数据看起来可能没有被正确解码。它可能有助于了解字节b'\xa5'映射到编码cp1252、cp1253、cp1254、cp1255、cp1256、cp1258、iso8859_15、iso8859_8、iso8859_9、latin_1、palmos中的“元”,但在编码cp437、cp850、cp857、cp858、cp860、cp862、cp865 (Cp858)中映射到“in”。

票数 1
EN

Stack Overflow用户

发布于 2021-10-19 16:22:00

str.encodebytes.decode的默认编码是utf-8 (这是一个可变宽度的字符编码)。使用固定长度的编码代替。应用utf-32来正确处理BMP以外的字符。

代码语言:javascript
复制
import struct

line = '00041235957A CORU¥A       ABC\n'

formats = ('4s 7s 15s 3s')
formats32 = '<' + ''.join([str(4*int(x))+'s' for x in formats.split('s')[:-1]])
st = struct.Struct(formats32)
fields = tuple(s.decode('utf_32_le') for s in st.unpack_from(line.encode('utf_32_le')))
print(fields)

结果:.\SO\69621626.py

代码语言:javascript
复制
('0004', '1235957', 'A CORU¥A       ', 'ABC')
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69621626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档