我的程序使用“iwlist scan”的输出生成报告。
除非网络名称(ESSID)包含非Ascii字符,否则它可以正常工作
IEEE802.11声明ESSID可能包含UTF8字符。但是,这些essid被iwlist报告为编码的字节串。例如:
ESSID: “F \ XC3 \ xAAte”
\ xC3 \ xAA实际上是“ê”的UTF-8编码
我找不到指定“打开”这些字节串应自动转换为UTF-8字符的方法
问题:解决我问题的最灵活方法是什么?
PS:作为测试案例,我将以下行放在一个文件中(比如xx):
ESSID: “F \ XC3 \ xAAte”
我执行:
open('xx','rb')。read()。decode('UTF-8')
我的结果是:
'ESSID:“f \ xC3 \ xAAte”\ n'
答案 0 :(得分:1)
这实际上是一个两步过程:将\xNN
代码转换为等效字节值,然后将这些字节从UTF-8转换为Unicode字符。 Python提供了unicode_escape
编解码器,使流程更简单。不幸的是,您需要一个额外的步骤 - 它不会将\xNN
转换为字节,它会将它们转换为字符,您需要将那些转换回等效字节。
所以你最终得到了3步转化。编码到latin1
是将字符转换为字节的黑客攻击。它的工作原理是因为Unicode使用Latin-1编码作为其前256个代码点,为您提供1:1映射。
with open(filename, 'rb') as f:
essid_raw = f.read()
essid = essid_raw.decode('unicode_escape').encode('latin1').decode('utf-8')
>>> essid_raw = b'ESSID:"f\xC3\xAAte"'
>>> essid = essid_raw.decode('unicode_escape').encode('latin1').decode('utf-8')
>>> print(essid)
ESSID:"fête"
答案 1 :(得分:0)
据我了解你的问题:
您的文件看起来根本没有Unicode字符,但它有一个转义字符串。因此,实际上有8个字符ê
,而不是一个\xC3\xAA
符号。因此,不应使用.decode("utf-8")
从Unicode解码,而应使用unicode转义字符(.decode('unicode_escape')
进行解码。
为了尝试这个,我用一个字符串创建了一个文件:
ESSID:"f\xC3\xAAte"
然后此脚本打印以下内容:
>>> open( 'file','rb').read().decode('UTF-8')
ESSID:"f\xC3\xAAte"
如果您使用unicode_escape,您将获得
>>> open( 'file','rb').read().decode('unicode_escape')
ESSID:"fête"
答案 2 :(得分:0)
我正在回答自己 找不到python解决方案所以我开发了我的 方法是删除'\ x'并将2个十六进制字符转换为一个字节。重复每个\ x。
def adapt( tb):
# this function converts the weird UTF8 escaping used by 'iwlist scan'
# iwlist outputs "f\xC3\xAAte" instead of "fête"
# caution : input is not sanitized
i = 0
while True:
# suppress \x and replace the following 2 characters by their hex value
i = tb.find( b'\\\x', i)
if i < 0: break
tb = tb[:i] + bytes( [int( tb[ i+2:i+4], 16)]) + tb[i+4:]
i += 1 # skip the preceding sequence
return tb
用法:
txt = adapt( open( 'xx','rb').read()).decode()
print( txt)
ESSID:"fête"
这是一个丑陋的黑客,但它工作正常。我很乐意更喜欢更好的解决方案 谢谢你的回答。