转换双斜杠utf8编码

2024-05-17 00:19:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我不能让它工作!我有一个来自save游戏文件解析器的文本文件,其中有一组以字节形式显示的UTF-8中文名称,如source.txt中所示:

\xe6\x89\x8e\xe5\x8a\xa0\xe6\x8b\x89

但是,不管我如何将它导入到Python(3或2)中,我最多只能得到这个字符串:

\\ xe6\\ x89\\ x8e\\ xe5\\ x8a\\ X10\\ xe6\\ x8b\\ x89

像其他线程建议的那样,我尝试将字符串重新编码为UTF-8,然后使用unicode转义对其进行解码,如下所示:

stringName.encode("utf-8").decode("unicode_escape")

但它会破坏原始编码,并将其作为字符串:

“æ\x89\x8eå\x8a\xa0æ\x8b\x89”(打印此字符串将导致:æåæ)

现在,如果我手动复制并粘贴b+文件名中的原始字符串并对其进行编码,我将得到正确的编码。例如:

b'\xe6\x89\x8e\xe5\x8a\xa0\xe6\x8b\x89'.encode("utf-8")

结果显示:“৔加拉”

但是,我不能用编程的方法。我连双刀都摆脱不了。

为了清楚起见,source.txt包含单个反斜杠。我尝试过多种方式导入,但这是最常见的:

with open('source.txt','r',encoding='utf-8') as f_open:
    source = f_open.read()

好的,所以我点击了下面的答案(我想),但这里是有效的:

from ast import literal_eval
decodedString = literal_eval("b'{}'".format(stringVariable)).decode('utf-8')

由于其他编码问题,我不能在整个文件中使用它,但是将每个名称提取为字符串(stringVariable),然后这样做就可以了!谢谢您!

更清楚地说,原始文件不仅仅是这些乱七八糟的utf编码。它只在某些领域使用它们。例如,以下是文件的开头:

{'m_cacheHandles': ['s2ma\x00\x00CN\x1f\x1b"\x8d\xdb\x1fr \\\xbf\xd4D\x05R\x87\x10\x0b\x0f9\x95\x9b\xe8\x16T\x81b\xe4\x08\x1e\xa8U\x11',
                's2ma\x00\x00CN\x1a\xd9L\x12n\xb9\x8aL\x1d\xe7\xb8\xe6\xf8\xaa\xa1S\xdb\xa5+\t\xd3\x82^\x0c\x89\xdb\xc5\x82\x8d\xb7\x0fv',
                's2ma\x00\x00CN\x92\xd8\x17D\xc1D\x1b\xf6(\xedj\xb7\xe9\xd1\x94\x85\xc8`\x91M\x8btZ\x91\xf65\x1f\xf9\xdc\xd4\xe6\xbb',
                's2ma\x00\x00CN\xa1\xe9\xab\xcd?\xd2PS\xc9\x03\xab\x13R\xa6\x85u7(K2\x9d\x08\xb8k+\xe2\xdeI\xc3\xab\x7fC',
                's2ma\x00\x00CNN\xa5\xe7\xaf\xa0\x84\xe5\xbc\xe9HX\xb93S*sj\xe3\xf8\xe7\x84`\xf1Ye\x15~\xb93\x1f\xc90',
                's2ma\x00\x00CN8\xc6\x13F\x19\x1f\x97AH\xfa\x81m\xac\xc9\xa6\xa8\x90s\xfdd\x06\rL]z\xbb\x15\xdcI\x93\xd3V'],
'm_campaignIndex': 0,
'm_defaultDifficulty': 7,
'm_description': '',
'm_difficulty': '',
'm_gameSpeed': 4,
'm_imageFilePath': '',
'm_isBlizzardMap': True,
'm_mapFileName': '',
'm_miniSave': False,
'm_modPaths': None,
'm_playerList': [{'m_color': {'m_a': 255, 'm_b': 255, 'm_g': 92,   'm_r': 36},
               'm_control': 2,
               'm_handicap': 0,
               'm_hero': '\xe6\x89\x8e\xe5\x8a\xa0\xe6\x8b\x89',

“m_hero”之前的所有信息:字段不是utf-8。因此,如果文件只是由这些假utf编码组成,使用ShadowRanger的解决方案是有效的,但是当我已经将m_hero解析为字符串并尝试转换它时,它就不起作用了。卡林的解决方案确实有效。


Tags: 文件字符串source编码utfxa0x00x8b
3条回答

你可以做一些愚蠢的事情,比如eval导出字符串:

import ast
s = r'\xe6\x89\x8e\xe5\x8a\xa0\xe6\x8b\x89'
print ast.literal_eval('"%s"' % s).decode('utf-8')
  • 注意:如果不希望攻击者访问您的系统,请使用ast.literal_eval

在你的案例中使用这个可能看起来像:

with open('file') as file_handle:
    data = ast.literal_eval('"%s"' % file.read()).decode('utf-8')

我认为这里真正的问题是可能有一个包含表示字节的字符串的文件(而不是一个只存储字节本身的文件)。因此,首先修复生成该文件的任何代码可能是更好的选择。不过,除此之外,这是我能想到的下一件最好的事情。。。

我假设您使用的是Python 3。在Python2中,默认情况下字符串是字节,因此它只对您有效。但是在Python3中,字符串是unicode的,并被解释为unicode,这就是为什么如果将字节字符串读为unicode会使这个问题变得更困难的原因。

这个解决方案的灵感来自于mgilson的回答。通过使用^{},我们可以将您的unicode字符串作为字节字符串进行实际计算:

from ast import literal_eval

with open('source.txt', 'r', encoding='utf-8') as f_open:
    source = f_open.read()
    string = literal_eval("b'{}'".format(source)).decode('utf-8')
    print(string)  # 扎加拉

问题是the ^{} codec is implicitly decoding the result of the escape fixes by assuming the bytes are ^{}, not ^{}。您可以通过以下方法解决此问题:

# Read the file as bytes:
with open(myfile, 'rb') as f:
    data = f.read()

# Decode with unicode-escape to get Py2 unicode/Py3 str, but interpreted
# incorrectly as latin-1
badlatin = data.decode('unicode-escape')

# Encode back as latin-1 to get back the raw bytes (it's a 1-1 encoding),
# then decode them properly as utf-8
goodutf8 = badlatin.encode('latin-1').decode('utf-8')

它(假设文件包含文本反斜杠和代码,而不是它们所表示的字节)留给您'\u624e\u52a0\u62c9'(这应该是正确的,我只是在一个没有对这些字符的字体支持的系统上,所以这只是基于Unicode转义的安全repr)。您可以在Py2中跳过一步,在第一阶段使用string-escape编解码器decode(我相信这将允许您省略.encode('latin-1')步骤),但是这个解决方案应该是可移植的,而且成本不应该太高。

相关问题 更多 >