如果我有这样的unicode:
'\x00B\x007\x003\x007\x00-\x002\x00,\x001\x00P\x00W\x000\x000\x009\x00,\x00N\x00O\x00N\x00E\x00,\x00C\x00,\x005\x00,\x00J\x00,\x00J\x00,\x002\x009\x00,\x00G\x00A\x00R\x00Y\x00,\x00 \x00W\x00I\x00L\x00L\x00I\x00A\x00M\x00S\x00,\x00 \x00P\x00A\x00R\x00E\x00N\x00T\x00I\x00,\x00 \x00F\x00I\x00N\x00N\x00E\x00Y\x00 \x00&\x00 \x00L\x00E\x00W\x00I\x00S\x00,\x00U\x00S\x00,\x001\x00\r\x00'
它以字符串格式从csv读入,但我想将其转换为人类可读的形式。它在我打印它时起作用,但我似乎无法弄清楚方法命令,将其保存为人类可读形式的变量。什么是最好的方法?
答案 0 :(得分:6)
你没有Unicode。不是还是。您有一系列字节,这些字节使用UTF-16 编码。您需要首先解码这些字节:
data.decode('utf-16-be')
打印它只是因为你的控制台忽略了每个UTF-16代码单元的大端对。
您的数据缺少Byte order mark,因此假设您在以下位置切割数据,我使用了UTF-16的utf-16-be
或 big endian 变体正确的字节。如果你没有,它也可能是 little endian。
因为它是我必须删除最后\x00
空字节以使其解码;当你将一个UTF-16代码单元(每2个字节)切成两半时,你粘贴了一个奇数而不是偶数个字节:
>>> s = '\x00B\x007\x003\x007\x00-\x002\x00,\x001\x00P\x00W\x000\x000\x009\x00,\x00N\x00O\x00N\x00E\x00,\x00C\x00,\x005\x00,\x00J\x00,\x00J\x00,\x002\x009\x00,\x00G\x00A\x00R\x00Y\x00,\x00 \x00W\x00I\x00L\x00L\x00I\x00A\x00M\x00S\x00,\x00 \x00P\x00A\x00R\x00E\x00N\x00T\x00I\x00,\x00 \x00F\x00I\x00N\x00N\x00E\x00Y\x00 \x00&\x00 \x00L\x00E\x00W\x00I\x00S\x00,\x00U\x00S\x00,\x001\x00\r\x00'
>>> s[:-1].decode('utf-16-be')
u'B737-2,1PW009,NONE,C,5,J,J,29,GARY, WILLIAMS, PARENTI, FINNEY & LEWIS,US,1\r'
您从中读取的文件可能包含BOM作为前两个字节。如果是这样,只需告诉您使用的任何内容来读取此数据以使用utf-16
作为编解码器,并且它将从这些第一个字节中找出正确的变体。
如果您使用的是Python 2,那么您希望研究csv
模块的Examples section,以获取可以以适合该模块的形式重新编码数据的代码;如果您包含该部分中的UnicodeReader
,则可以像这样使用它:
with open(yourdatafile) as inputfile:
reader = UnicodeReader(inputfile, encoding='utf-16')
for row in reader:
# row is now a list with unicode strings
演示:
>>> from StringIO import StringIO
>>> import codecs
>>> f = StringIO(codecs.BOM_UTF16_BE + s[:-1])
>>> r = UnicodeReader(f, encoding='utf-16')
>>> next(r)
[u'B737-2', u'1PW009', u'NONE', u'C', u'5', u'J', u'J', u'29', u'GARY', u' WILLIAMS', u' PARENTI', u' FINNEY & LEWIS', u'US', u'1']
如果您使用的是Python 3,只需将encoding
参数设置为open()
函数utf-16
,然后按原样使用csv
模块。