2014-11-19 6 views

ответ

3

Нет, такой функции нет, потому что файлы не записывают, какой кодек использовался для записи содержащегося текста.

Если есть больше контекста (например, более конкретный формат, такой как HTML или XML), то вы можете определить кодек, потому что стандарт определяет значение по умолчанию или позволяет аннотирования данных с кодеком, но в противном случае вы снижаются к угадыванию на основе содержимого (что и делают такие инструменты, как chardet).

Для файла, который может изменить любой пользователь, у вас нет никакой надежды, кроме как четко документировать, какой кодек следует использовать.

+0

Я также думаю, что есть больше контекста, но нет. Большинство строк (около 5k) находятся в utf-8, но на некоторых строках я получаю UnicodeDecodeError ... :( – alabamajack

+0

@alabamajack: лучшее, что вы можете сделать, это использовать режим ошибок, который либо игнорирует такие ошибки или заменяет недоказуемые байты с заменяющими символами ('?' или ' '). –

+0

Интересно, что существуют системы, которые * делают * записывать кодировку с каждым файлом (например, средний уровень IBM). Но, конечно, если они вообще взаимодействуют с «внешний мир», они могут получать файлы без информации о кодировании или отправлять файлы в другие системы, которые не соблюдают предоставленную информацию кодирования. –

2

Вы можете использовать сторонний модуль chardet.

>>> import chardet 
>>> chardet.detect(b'\xed\x95\x9c\xea\xb8\x80') # u'한글'.encode('utf-8') 
{'confidence': 0.7525, 'encoding': 'utf-8'} 
>>> chardet.detect(b'\xc7\xd1\xb1\xdb') 
{'confidence': 0.99, 'encoding': 'EUC-KR'} # u'한글'.encode('euc-kr') 

Примечание: chardet не является надежным, и если файл достаточно мал, можно легко догадаться, не так.

+2

'chardet' не является надежным, и если файл достаточно мал, можно легко ошибаться. –

+0

Следует отметить, что 'chardet' не поставляется с Python, а является сторонним пакетом. – Dolda2000

+0

хорошая идея, но не может этого сделать, потому что установка python должна быть адаптирована вручную на столько ПК ... – alabamajack

1

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

# Add whichever you want to the list, but only end it in a codec like latin1 that never fails 
codecs = ["utf-8", "euc-kr", "shift-jis", "latin1"] 

def try_decode(text): 
    for codec in codecs: 
     try: 
      return text.decode(codec) 
     except UnicodeError: 
      continue 
+0

хороший трюк, немного грязный, если вы не знаете, какой кодек вам нужен ^^;) – alabamajack

+0

Конечно, но поскольку вы действительно этого не знаете, я вряд ли думаю, что есть другие способы сделать это. Я имею в виду, что это в основном то, что делает «chardet», но только с немного большей изощренностью. – Dolda2000

+0

Я должен сказать, что я был немного удивлен, что есть какой-либо кодек, который «никогда не сработает», но после небольшого эксперимента, кажется, что вы всегда можете * декодировать * с помощью «latin1» (по крайней мере, на моем ПК с Windows с Python 2.7). Я думаю, это стоит отметить, особенно для тех, кто не на 100% уверен в вопросах кодирования символов (что, откровенно говоря, большинство из нас!), что, хотя кодек 'latin1' всегда« преуспевает »при создании строки Unicode, эта строка может быть полным мусором. Может случиться так, что нам было бы лучше использовать, скажем, «shift-jis» и просто игнорировать/заменять несколько байтов здесь и там. –

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