2016-07-21 3 views
-2

Если у меня есть некоторый юникод, как это:ошибки питона Юникода преобразовать в напечатанных значения

'\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 в формате строка, но я хотел бы, чтобы преобразовать его в читаемый вид. Он работает, когда я печатаю его, но, похоже, я не могу понять команду подхода, чтобы сохранить ее в переменной в удобочитаемой форме. Каков наилучший подход?

+1

У вас есть строка байтов –

+1

вы попробовать 'печати (x.encode («utf8»))' – karthikr

+0

я печать будет работать, я хочу, напечатанный текст, который будет сохранен в переменной – Rob

ответ

6

У вас нет Юникода. Не более . У вас есть серия байтов, и эти байты используют кодировку UTF-16 . Вы должны декодировать эти байты первого:

data.decode('utf-16-be') 

Печать это работает только потому, что ваша консоль игнорирует большую часть большой обратный порядок байт пары каждого UTF-16 программный модуль.

Ваши данные не хватают Byte order mark, поэтому мне пришлось использовать utf-16-be или большого байтов вариант UTF-16, при условии, что вы режете данные в нужных байтах. Это также может быть маленький 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' 

Файл, который вы читаете эти строки из вероятно содержит спецификацию как первые два байта. Если да, просто скажите, что вы используете для чтения этих данных, чтобы использовать utf-16 в качестве кодека, и он будет определять правильный вариант из этих первых байтов.

Если вы используете Python 2, вы хотите изучить Examples section модуля csv для кода, который может перекодировать ваши данные в форме, подходящей для этого модуля; если включить 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 как есть.

Смежные вопросы