Как определить кодировку текстового файла c

Обновлено: 02.07.2024

печатать(x,y) вместо печатать x, y

Вам может понадобиться
open(filename, encoding="utf-8")
вместо open(filename). См. примечание ниже.

Обзор видео

  • Чтобы открыть текстовый файл в коде, используйте встроенную в Python функцию open(). В функции open() введите строку, содержащую путь к местоположению вашего текстового файла (в данном случае это выглядит как open('C:/Users/mybringback/Desktop/ pg16328.txt'), ваше местоположение, конечно, будет выглядеть иначе). После открытия текстового файла вы можете указать Python, что с ним делать, определив его как переменную. Например, если ввести booktxt = book.readlines(), "booktxt" будет определено как ваш текстовый файл и позволит вызывать его в вашей программе на читаемой построчной основе.
  • После определения этой переменной достаточно ввести booktxt, чтобы отобразить весь текстовый файл от начала до конца в окне IDLE. Хотя эта функция может быть полезна в других обстоятельствах, часто ваш текст будет слишком длинным и громоздким, чтобы его можно было вызвать таким образом, как в случае с большим текстовым файлом, используемым в этом руководстве. В этом случае вы также можете вызвать выбранные строки из вашего текста, поместив конкретный номер строки в скобки рядом с вашей переменной. Например, booktxt[0] вызовет первую строку текста из вашего файла, которая в используемом нами тексте является информацией о форматировании.
  • Чтобы вспомнить длину текстового файла в словах, введите len(booktxt). Дополнительные сведения о функции len() см. в Уроке 11.

Подробнее

  • Если вы являетесь пользователем Mac, не указывайте букву диска "C:" в пути к файлу. Дерево каталогов Mac просто начинается с "/", который называется корнем.
  • Даже если следовать в точности инструкциям Эда и использовать точный файл Beowulf, некоторые из вас (в основном в Windows) получат следующее неожиданное сообщение об ошибке:

Это означает, что метод кодирования текстового файла отличается от кодировки по умолчанию в вашей системе. Эд не получил эту ошибку, потому что он работает в Python 2.7, который иначе обрабатывает кодировку текста. В Python 3 чаще всего нам нужно указать систему кодирования при открытии файла с помощью переключателя encoding="xxx":


Этот текстовый файл может принимать удивительное количество различных форматов. Текст может быть закодирован как ASCII, UTF-8, UTF-16 (с прямым или обратным порядком байтов), Windows-1252, Shift JIS или любой из десятков других кодировок. Файл может начинаться или не начинаться с метки порядка байтов (BOM). Строки текста могут заканчиваться символом перевода строки \n (обычно для UNIX), последовательностью CRLF \r\n (обычно для Windows) или, если файл был создан в более старой системе, какой-либо другой последовательностью символов.

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

А2 С2 А2 С2 А2 С2

  • файл UTF-8, содержащий «¢¢¢»
  • файл UTF-16 (или UCS-2) с прямым порядком байтов, содержащий «ꋂꋂꋂ»
  • файл UTF-16 с прямым порядком байтов, содержащий «슢슢슢»
  • файл Windows-1252, содержащий «Â¢Â¢Â¢»

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

Эта проблема существует уже некоторое время. К счастью, ландшафт текстовых файлов со временем стал проще, и UTF-8 побеждает другие кодировки символов. В настоящее время более 95% Интернета доставляется с использованием UTF-8. Впечатляет, как быстро это число изменилось; еще в 2006 году этот показатель составлял менее 10 %.


Однако UTF-8 еще не завоевала мир. Например, редактор реестра Windows по-прежнему сохраняет текстовые файлы в кодировке UTF-16. При записи текстового файла из Python кодировка по умолчанию зависит от платформы; на моем ПК с Windows это Windows-1252. Другими словами, проблема неоднозначности существует и сегодня. И даже если текстовый файл закодирован в UTF-8, все равно существуют различия в формате, поскольку файл может начинаться или не начинаться со спецификации и может использовать окончания строк в стиле UNIX или Windows.

Как Plywood C++ Framework загружает текст

Plywood – это кроссплатформенная платформа C++ с открытым исходным кодом, которую я выпустил два месяца назад. При открытии текстового файла с помощью Plywood у вас есть несколько вариантов:

  • Если вы заранее знаете точный формат текстового файла, вы можете вызвать FileSystem::openTextForRead() , передав ожидаемый формат в структуре TextFormat.
  • Если вы не знаете точный формат, вы можете вызвать FileSystem::openTextForReadAutodetect() , который попытается автоматически определить формат и вернуть его вам.

Входной поток, возвращаемый этими функциями, никогда не начинается со спецификации, всегда кодируется в UTF-8 и всегда заканчивается каждой строкой ввода одним символом возврата каретки \n независимо от исходного формата входного файла. Преобразование выполняется на лету, если это необходимо. Это позволяет приложениям Plywood работать с одной внутренней кодировкой.

Автоматическое определение формата

Вот как в настоящее время работает автоматическое определение формата текста Plywood:

Начинается ли файл со спецификации?

Использовать кодировку спецификации

Может ли файл быть декодирован как UTF-8 без каких-либо ошибок или контрольных кодов?

При декодировании в формате UTF-8 возникают ли ошибки декодирования более чем в 25 % кодовых точек, отличных от ASCII?

Определить тип окончания строки (LF или CRLF)

Plywood анализирует до первых 4 КБ входного файла, чтобы угадать его формат. Первые две проверки обрабатывают подавляющее большинство текстовых файлов, с которыми я сталкивался. В UTF-8 много недопустимых последовательностей байтов, поэтому, если текстовый файл может быть декодирован как UTF-8 и не содержит управляющих кодов, то это почти наверняка файл UTF-8. (Управляющим кодом считается любая кодовая точка меньше 32, за исключением табуляции, перевода строки и возврата каретки.)

Только когда мы входим в нижнюю половину блок-схемы, начинают происходить некоторые догадки. Во-первых, Plywood решает, как лучше интерпретировать файл: как UTF-8 или как обычные байты. Это предназначено для перехвата, например, текста, закодированного в Windows-1252, в котором используются символы с диакритическими знаками. В Windows-1252 французское слово détail кодируется как 64 E9 74 61 69 6C , что вызывает ошибку декодирования UTF-8, поскольку UTF-8 ожидает, что после E9 будет байт в диапазоне 80. - БФ. После определенного количества таких ошибок Plywood будет отдавать предпочтение обычным байтам, а не UTF-8.

Система подсчета очков

Оценки делятся на общее количество декодированных символов, после чего выбирается лучшая оценка. Если вам интересно, откуда взялись эти значения баллов, я их придумал! Вероятно, они еще не оптимальны.

Комплект тестов

В репозитории Plywood на GitHub вы найдете папку, содержащую 50 различных текстовых файлов в различных форматах. Все эти файлы идентифицируются и правильно загружаются с помощью FileSystem::openTextForReadAutodetect() .


Многие современные текстовые редакторы выполняют автоматическое определение формата, как и Plywood. Из любопытства я попробовал открыть этот набор текстовых файлов в нескольких редакторах:

    правильно определил формат 38 из 50 файлов. Он не работает со всеми файлами UTF-16, в которых отсутствует спецификация, за исключением файлов с прямым порядком байтов, которые в основном состоят из символов ASCII. правильно определил формат 42 файлов. Когда текст состоит в основном из ASCII, он угадывается правильно независимо от кодировки. правильно определил формат 40 файлов. Это похоже на Sublime Text, но не работает с файлами Windows-1252, содержащими символы с диакритическими знаками.
  • И, пожалуй, самое впечатляющее то, что Блокнот Windows правильно определил формат целых 42 файлов! Он правильно угадывает все файлы UTF-16 с прямым порядком байтов без спецификаций, но не работает со всеми файлами UTF-16 с прямым порядком байтов без спецификаций.

Следует признать, что это был нечестный конкурс, так как весь набор тестов был сделан вручную для Plywood. И в большинстве случаев, когда редактор выходил из строя, это было в файле UTF-16, в котором отсутствовала спецификация, что кажется редким форматом — ни один из редакторов не позволяет сохранить такой файл.

Стоит упомянуть, что именно эти текстовые редакторы послужили источником вдохновения для стратегии автоматического обнаружения Plywood. Работа с Unicode всегда была сложной в C++ — ситуация достаточно плохая, комитет по стандарту C++ недавно сформировал исследовательскую группу, занимающуюся его улучшением. Между тем, я всегда задавался вопросом: почему загрузка текста в C++ не может быть такой же простой, как в современном текстовом редакторе?

Если вы хотите улучшить Plywood любым из способов, упомянутых в этом посте, не стесняйтесь участвовать на GitHub или на сервере Discord. И если вам нужен только исходный код, определяющий кодировку текста, но вы не хотите внедрять саму Plywood, я понимаю! Не стесняйтесь копировать исходный код, как считаете нужным — все лицензировано MIT.

Познакомьтесь с Plywood, кроссплатформенной платформой C++ с открытым исходным кодом:

У меня возникли проблемы с файлами субтитров в видео omxplayer. Чтобы решить эту проблему, мне пришлось преобразовать кодировку Windows-1250 в UTF-8. Мой вопрос: как я могу увидеть для какого-то конкретного файла, какая кодировка используется?

Да. Я уже менял кодировку (в 1 файле). Но у меня их много, и я хотел сделать небольшой скрипт, который бы контролировал их все, а затем при необходимости скрывал. Но я полагаю, что я могу просто преобразовать их все.Не будет никакого вреда, если некоторые из них уже будут в UTF-8. Верно?

3 ответа 3

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

Тем не менее, вы можете легко проверить, можно ли успешно декодировать весь файл каким-либо образом (но не обязательно правильно) с использованием определенного кодека. Если вы обнаружите какие-либо байты, недопустимые для данной кодировки, это должно быть что-то другое.

Проблема в том, что многие кодеки похожи и имеют одинаковые «допустимые шаблоны байтов», просто интерпретируя их как разные символы. Например, ä в одной кодировке может соответствовать é в другой или ø в третьей. Компьютер на самом деле не может определить, какой способ интерпретации байта приводит к правильно читаемому тексту (если, возможно, вы не добавите словарь для всех видов языков и не разрешите ему выполнять проверку орфографии). Вы также должны знать, что некоторые наборы символов на самом деле являются подмножествами других, например, кодировка ASCII является частью наиболее часто используемых кодеков, таких как некоторые из семейства ANSI или UTF-8. Это означает, например, что текст, сохраненный как UTF-8, который содержит только простые латинские символы, будет идентичен тому же файлу, сохраненному как ASCII.

Однако давайте вернемся от объяснения того, что вы не можете сделать, к тому, что вы действительно можете сделать:

Для базовой проверки текстовых файлов ASCII/не-ASCII (обычно UTF-8) вы можете использовать команду file. Однако он не знает многих кодеков и проверяет только первые несколько килобайт файла, предполагая, что остальные не будут содержать никаких новых символов. С другой стороны, он также распознает другие распространенные типы файлов, такие как различные скрипты, документы HTML/XML и многие форматы двоичных данных (хотя все это неинтересно для сравнения текстовых файлов), и может печатать дополнительную информацию о том, есть ли очень длинные строки или что-то еще. тип последовательности новой строки (например, UNIX: LF, Windows: CR+LF).

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

Ниже myfile открывается для записи. Во втором случае переключатель 'a' обеспечивает добавление нового содержимого в конец существующего текстового файла. Если бы вместо этого вы использовали 'w', исходный файл был бы перезаписан.

Есть еще одна важная информация: кодировка. Некоторые файлы, возможно, придется читать как определенный тип кодировки, а иногда вам нужно записать файл в определенной системе кодирования. В таких случаях оператор open() должен включать спецификацию кодировки с переключателем encoding='xxx':

Чтение из файла

Хорошо, мы знаем, как открывать и закрывать файловый объект. Но каковы фактические команды для чтения? Существует несколько методов.

Сначала .read() считывает все текстовое содержимое файла как одну строку. Ниже файл считывается в переменную с именем marytxt, которая становится строковым объектом. Загрузите mary-short.txt и попробуйте сами.

Затем .readlines() считывает все текстовое содержимое файла в виде списка строк, каждая из которых заканчивается разрывом строки. Ниже вы можете видеть, что marylines — это список строк, где каждая строка является строкой из mary-short.txt.

Наконец, вместо того, чтобы загружать все содержимое файла в память, вы можете выполнять итерацию по файловому объекту строка за строкой, используя for . в цикле. Этот метод более эффективно использует память и поэтому рекомендуется при работе с очень большими файлами. Ниже открывается файл bible-kjv.txt, и выводится любая строка, содержащая smite. Скачайте файл bible-kjv.txt и попробуйте сами.

Запись в файл

Методы записи также входят в пару: .write() и .writelines(). Как и соответствующие методы чтения, .write() обрабатывает одну строку, а .writelines() обрабатывает список строк.

Ниже .write() каждый раз записывает одну строку в указанный выходной файл:

Обратите внимание, что все строки в примерах имеют разрыв строки '\n' в конце. Без него все строки будут выводиться на одной строке, что и происходило в Уроке 13. В отличие от оператора print, который печатает строку на отдельной новой строке, методы записи не будут фиксироваться. на символе новой строки -- вы должны не забыть указать '\n', если хотите, чтобы строка занимала отдельную строку.

Распространенные ошибки


Известно, что файловый ввод-вывод чреват камнем преткновения для начинающих программистов. Ниже приведены наиболее распространенные из них.

Ошибка "Нет такого файла или каталога"

Вы получаете эту ошибку, потому что Python не смог найти файл для чтения. Убедитесь, что вы указываете правильный путь и имя файла. Прочитайте первый путь к файлу и CWD. Также см. этот, этот и этот FAQ.

Проблемы с кодировкой

"UnicodeDecodeError" означает, что у вас возникла проблема с кодировкой файла. Каждый компьютер имеет свою общесистемную кодировку по умолчанию, а файл, который вы пытаетесь открыть, имеет другую кодировку, скорее всего, какую-то версию Unicode. В этом случае следует указать кодировку с помощью переключателя encoding='xxx' при открытии файла. Если вы не уверены, какую кодировку использовать, попробуйте 'utf-8', 'utf-16' и 'utf-32'. .

Все содержимое файла можно прочитать только ОДИН РАЗ за одно открытие

И .read(), и .readlines() имеют концепцию курсора. После выполнения любой команды курсор перемещается в конец файла, не оставляя больше места для чтения. Таким образом, как только содержимое файла будет прочитано, следующая попытка чтения из файлового объекта приведет к созданию пустого объекта данных. Если по какой-либо причине вам необходимо снова прочитать содержимое файла, вы должны закрыть и снова открыть файл.

Можно записать только строковый тип

Методы записи работают только со строками: .write() принимает одну строку, а .writelines() принимает список, содержащий только строки. Данные нестрокового типа должны быть сначала приведены к строковому типу с помощью функции str().

Ваш выходной файл пуст

Это случается с каждым: вы что-то пишете, открываете файл для просмотра и обнаруживаете, что он пуст. В других случаях содержимое файла может быть неполным. Любопытно, не так ли? Ну, причина проста: ВЫ ЗАБЫЛИ .close(). Запись происходит в буферы; очистка последнего буфера записи не происходит до тех пор, пока вы не закроете свой файловый объект. ВСЕГДА НЕ ЗАКРЫВАЙТЕ ФАЙЛ-ОБЪЕКТ.

Читайте также: