【发布时间】:2021-10-18 19:33:46
【问题描述】:
评论:虽然我理解对数据“准确性”的一些担忧,但我认为这对于这个问题来说真的无关紧要。数据就是这样。假设是这样,会对可能的解决方案感兴趣。
---------
我需要读取包含具有 unicode 字符的行的文件。这些行包含多列,每列都从一个固定位置开始。
这里是一个例子(我已经用连字符来表示单个列的结束位置,连字符实际上不是字符串的一部分)。
0004-1235957-A CORU¥A -ABC
在上面的示例中,第 1 列占据前 4 个位置,第 2 列占据接下来的 7 个位置,第 3 列占据接下来的 15 个位置,第 4 列占据接下来的 3 个位置,依此类推。
我正在使用以下代码来解析这一行:
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)
这是我得到的输出:
('0004', '1235957', 'A CORU¥A ', ' AB')
如果您查看最后一列,它实际上被错误地读取了。原因是在 unicode 中,字符 '¥' 占用两个字节,这导致只有前 14 个字符(和 15 个字节)被读取,第 4 列从以下位置读取。
我想要的是一种读取第 3 列的 15 个 字符 而不是 15 个 字节 的方法,这与数据中存在的编码无关。即使我尝试在线使用子字符串方法,我也会得到相同的行为。
请专家对此提供一些指导吗?谢谢。
【问题讨论】:
-
该示例看起来应该输入
A CORUÑA(它是西班牙的一个城市),带有一个带波浪号的字母 N,而不是日元货币符号。所以可能有一个解码步骤出错了。您可能正在处理 8 位编码,其中每个字符实际上是 1 个字节。你是怎么打开文件的? -
文件不包含 Unicode 字符。它们包含表示编码的 Unicode 字符的字节。编码很重要,可能看起来像单个 Unicode 字符的内容可能会占用多个字节,具体取决于编码。如果您只想拆分现有的 Unicode 字符串,只需使用字符串切片而不是编码为字节,或者如果您想使用 struct 模块,则使用单字节编码对其进行编码,但请注意垃圾输入垃圾输出。
-
@lenz 这是一个简单的mojibake 案例
'Ñ'.encode( 'cp850').decode( 'cp1252') == '¥'返回True...