【问题标题】:How to decode a text in python3?如何在python3中解码文本?
【发布时间】:2021-05-08 22:05:18
【问题描述】:

我有一个文本 Aur\xc3\xa9lien 并想用 python 3.8 对其进行解码。

我尝试了以下

import codecs
s = "Aur\xc3\xa9lien"
codecs.decode(s, "urf-8")
codecs.decode(bytes(s), "urf-8")
codecs.decode(bytes(s, "utf-8"), "utf-8")

但它们都没有给出正确的结果Aurélien

如何正确做?

没有基本的、通用的、权威的简单页面来描述所有这些 python 编码吗?

【问题讨论】:

  • s = "Aur\xc3\xa9lien"; b = bytes(s, 'latin-1'); print(b.decode('utf-8'))
  • 注意:你的“s”实际上并不是一个字符串,而是一个字节序列,所以你应该在它前面加上一个b。您正在使用 Python 的一个特殊功能(它允许将二进制字符放在 Unicode 序列中)。
  • 我从文件中读取了该字符串。如何在现有字符串前面加上'b'?
  • 如何从文件中读取字符串?您可能使用了错误的open 命令。你使用哪个参数?通常open 读取一个文本文件,并且您应该有一个 unicode 字符串(带有替换字符)。但是在正常情况下,您会得到这样的“字符串”。要获得二进制字符串,只需在 open 中使用 'b'
  • 注意:你应该在回复时标记人。 (你有自动标记,因为你是提问者,当有人回复我的答案时我会得到它)。如何读取 csv 文件?通常我使用with open('file.cvs', encoding='utf8' as f: for line in f.readlines(): fields=line.split(',')。但是您可能正在使用模块? csv 模块?你如何阅读文件? [很久以前,在早期的 3.x 版本中,csv 在 Unicode 文件方面存在问题]

标签: python python-3.x encoding


【解决方案1】:

首先找到字符串的编码,然后对其进行解码...为此,您需要通过在原始字符串的前面添加字母“b”来创建一个字节字符串。

试试这个:

import chardet

s = "Aur\xc3\xa9lien"
bs = b"Aur\xc3\xa9lien"

encoding = chardet.detect(bs)["encoding"]

str = s.encode(encoding).decode("utf-8")

print(str)

如果您正在从文件中读取文本,则可以使用 magic 库检测编码,请参见此处:https://stackoverflow.com/a/16203777/1544937

【讨论】:

  • 我怎么知道原始字符串是用'latin1'编码的?
  • @Alex 我已经更新了我的答案,以编程方式检测编码。
  • @Alex 我还添加了一个链接,如果文本来自文件而不是代码中的字符串,则可以帮助您检测编码。
  • 但问题不在于检测编码(显然是 UTF-8)。理论上 Python 字符串没有编码。问题是 Python 字符串有一些字符作为二进制数据,而不是解释为 unicode 代码点(这是 Python 的一个隐藏/不太为人所知的特性 [大多数程序员不应该看到它])。
【解决方案2】:

您将UTF-8 解码为latin-1,因此解决方案是编码为latin-1,然后解码为UTF-8

s = "Aur\xc3\xa9lien"
s.encode('latin-1').decode('utf-8')
print(s.encode('latin-1').decode('utf-8'))

Output
Aurélien

【讨论】:

  • 我怎么知道它是 'latin-1'?
  • @Alex 在latin1 中,每个字符正好是一个字节长。在utf8 中,一个字符可以包含多个字节。因此,utf8 比 latin1 有更多的字符。此外,如果您想了解更多信息,则可以查看此答案。 stackoverflow.com/questions/2708958/…
  • 但在实际文本中有一个字符é 是8 个字节长。不?对不起,我不明白。 é=\xc3\xa9
  • é 实际上是 16 位或 2 字节长。您可以通过将其指定为 bytes b = b'\xc3\xa9' 来亲自查看。看到长度是2len(b)。获取bytes 的十进制值。 byte1 = b[0]195byte2 = b[1]169。然后将它们格式化为二进制。 print(f'{byte1:b}') 返回 '11000011'print(f'{byte2:b}') 返回 '10101001'。在幕后utf-8 正在读取二进制位并将它们转换为它们被解码为的字符。有时以 8 位为单位。有时更多。
  • 这个答案比我stackoverflow.com/a/27939161/12479639 解释得更好。归结为,它从磁盘读取的 8 位值意味着是否包含接下来的 8 位。
【解决方案3】:

你的字符串不是一个 Unicode 序列,所以你应该在它前面加上 b

import codecs
b = b"Aur\xc3\xa9lien"
b.decode('utf-8')

所以你有预期:'Aurélien'

如果你想使用s,你应该使用mbcslatin-1mac_roman或任何8位编码。没关系。这样的 8 位编解码器可以正确获取字符串中的二进制字符(1 对 1 映射)。所以你得到一个字节数组(所以现在你可以使用这个答案的第一部分,所以你可以解码二进制字符串。

【讨论】:

  • 我从文件中读取了该字符串。如何在 a that 前面加上“b”?
  • 如果您从文件中读取字符串,您应该写下您的问题,以及如何读取字符串。让这样的字符串从文件中读取数据是不正常的。真的,对于读取文件的默认或预期行为来说,这还很遥远
  • 不管怎样,问题的第二部分告诉你怎么做,如果你有一个带有二进制数据的字符串。
猜你喜欢
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
相关资源
最近更新 更多