Pyparsing, Python 3 и знак порядка байтов Unicode

У меня есть текстовый файл в кодировке UTF-8 с присутствующей меткой порядка байтов, то есть первые несколько байтов равны EF BB BF 0D 0A 4D... (это файл решения Visual Studio, созданный VS 2013).

Я пытаюсь проанализировать это с помощью PyParsing, используя метод parseFile() и Python 3. В Python 2 я мог бы сделать это:

import pyparsing as pp
bom = pp.Optional(unicode(unichr(0xfeff)).encode('utf-8')).suppress()

чтобы получить необязательную метку порядка байтов. Но в Python 3 функции unicode и unichr исчезли, поскольку все строки имеют кодировку Unicode. Итак, я попробовал это:

bom = pp.Optional(chr(0xfeff)).suppress()

и это:

bom = pp.Optional('\ufeff').suppress()

но ни один из них не соответствует началу файла. Я некоторое время гуглил, но не могу найти ничего подходящего.

Как я могу сопоставить (или просто игнорировать!) Знак порядка байтов Unicode?


person Tom    schedule 01.02.2016    source источник
comment
Разве файлы решений Visual Studio не являются XML?   -  person Wayne Werner    schedule 01.02.2016
comment
Эм, не те, на которые я смотрю. Файлы проекта точно есть, а файлы решений нет.   -  person Tom    schedule 01.02.2016


Ответы (2)


Кажется, проблема здесь в том, что кодировка по умолчанию, используемая при чтении файла с использованием метода parseFile(), — это ASCII, поэтому метка порядка байтов в кодировке UTF-8 не заканчивается как U+FEFF, она заканчивается как ASCII EF BB BF. Чтобы обойти это, вы можете явно открыть файл и указать кодировку. Вместо этого:

p.parseFile('filename.sln')

сделай это:

p.parseFile(open('filename.sln', encoding='utf-8'))

Тогда метку порядка байтов можно пропустить с помощью следующего синтаксического анализатора:

bom = pp.Optional(chr(0xfeff)).suppress()
person Tom    schedule 01.02.2016
comment
Или откройте файл, прочитайте содержимое с помощью .read(), а затем вызовите parseStringparseFile — это просто минимальная удобная оболочка вокруг parseString. - person PaulMcG; 01.02.2016

Откройте файл, используя тип кодировки utf_8_sig:

p.parseFile(open('filename.sln', encoding='utf_8_sig'))

Спецификация будет подавлена, если она присутствует.

Из модуля кодеков:

При кодировании спецификация в кодировке UTF-8 будет добавлена ​​к байтам в кодировке UTF-8. Для кодировщика с отслеживанием состояния это делается только один раз (при первой записи в поток байтов). Для декодирования необязательная спецификация в кодировке UTF-8 в начале данных будет пропущена.

person Alastair McCormack    schedule 01.02.2016