Как читать файлы в кодировке ANSI и Unicode в Python

Я пытаюсь написать функцию с использованием Python, в которой пользователь вводит корневой каталог и ключевые фразы для поиска. Затем моя функция просматривает весь каталог, чтобы найти и вывести строки из файлов, которые содержат введенные ключевые фразы. В настоящее время мой скрипт может читать и выводить строки из файлов, закодированных с помощью ANSI, но не Unicode. Пожалуйста, дайте мне знать, как я могу изменить свой код, чтобы мой скрипт мог выполнять поиск по обоим типам закодированных файлов. Я относительно новичок в Python, спасибо!

Мой скрипт Python:

import os

def myFunction(rootdir, keyPhrases):

    path = rootdir # Enter the root directory you want to search from

    key_phrases = [keyPhrases] # Enter here the key phrases in the lines you hope to find 
    key_phrases = [i.replace('\n','') for i in key_phrases] #In case an \n is added to the end of the string when the parameter is passed to the function

    # This for loop allows all sub directories and files to be searched
    for (path, subdirs, files) in os.walk(path): 
        files = [f for f in os.listdir(path) if f.endswith('.txt') or f.endswith('.log')] # Specify here the format of files you hope to search from (ex: ".txt" or ".log")
        files.sort() # file is sorted list

        files = [os.path.join(path, name) for name in files] # Joins the path and the name, so the files can be opened and scanned by the open() function

        # The following for loop searches all files with the selected format
        for filename in files:

                # Opens the individual files and to read their lines
                with open(filename) as f:
                    f = f.readlines()

                # The following loop scans for the key phrases entered by the user in every line of the files searched, and stores the lines that match into the "important" array
                for line in f:
                    for phrase in key_phrases: 
                        if phrase in line:
                            print(line)
                            break 

    print("The end of the directory has been reached, if no lines are printed then that means the key phrase does not exist in the root directory you entered.")

Что вы имеете в виду под «закодированным с помощью Unicode»? Или, если на то пошло, «закодировано с помощью ANSI»? Вы имеете в виду UTF-16-LE и любую другую 8-битную кодировку OEM (Windows)?

abarnert 01.06.2018 01:39

Попробуйте: with open(filename, encoding='utf-8') as f:

James 01.06.2018 01:40

В качестве примечания: посмотрите справку для str.endswith: может потребоваться кортеж суффиксов для проверки всех сразу, вместо необходимости отдельной проверки endswith для каждого из них.

abarnert 01.06.2018 01:40

Привет, Джеймс, спасибо за ответ. Когда я попробовал ваше решение, я получил сообщение «UnicodeDecodeError: кодек 'utf-8' не может декодировать байт 0xff в позиции 0: недопустимый начальный байт». Вы знаете, как я могу это решить? Спасибо.

D. Wu 01.06.2018 01:48

Привет, Абертнерт, и спасибо за ваш ответ. Я не совсем уверен, что вы имеете в виду под UTF-16-LE и 8-битной кодировкой OEM. Когда я проверяю кодировку, открывая файл в блокноте и нажимая «Сохранить как», кодировка отображается как ANSI или Unicode. Спасибо за заметку, я постараюсь использовать str.endswith, а не два оператора endwith.

D. Wu 01.06.2018 01:51

@ D.Wu. Вам понадобится что-то вроде Chardet для определения кодировки произвольных файлов.

ekhumoro 01.06.2018 01:58

@ekhumoro Спасибо за предложение, я только что загрузил chardet-3.0.4.tar.gz в свою папку python 3.6 и папку с моим скриптом python. Однако, когда я «импортирую chardet» в свой скрипт Python, Visual Studio определяет это как ошибку, говоря, что она не может импортировать chardet. Не могли бы вы рассказать мне, как решить эту проблему и правильно ее использовать? Спасибо!

D. Wu 01.06.2018 02:04

@ D.Wu. Избавьтесь от Visual Studio и используйте подходящую IDE для Python. Или просто напишите код в стандартном текстовом редакторе и запустите его в командном окне.

ekhumoro 01.06.2018 10:56

Юникод - это то, что Блокнот Windows называет UTF16. Используйте utf16, чтобы открыть его. Если вы используете Visual Studio, установите Python Tools for Windows для поддержки Python.

Mark Tolonen 01.06.2018 18:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
9
60
1

Ответы 1

В файлах Windows с кодировкой «Unicode» (UTF16) первые 2 байта обычно являются маркером порядка байтов (BOM) со значением 0xFF 0xFE. Это указывает на кодировку UTF16 с прямым порядком байтов. Файлы "ANSI" (обычно Windows-1252) не имеют маркера.

Когда вы пытаетесь прочитать файл UTF16, как если бы он был закодирован с другой 8-битной кодировкой, например UTF8, Windows-1252 или ASCII вы увидите исключение UnicodeDecodeError, потому что 0xFF не является допустимым байтом в этих кодировках (или допустимым стартовым байтом для UTF-8).

Итак, если вы точно знаете, что файлы будут закодированы в кодировке UTF-16-LE или Windows-1252, тогда вы можете проверить спецификацию UTF16 в начале файла и открыть файл с этой кодировкой, если она обнаружена:

import sys
from codecs import BOM_UTF16_LE

def get_file_encoding(filename, default=None):
    with open(filename, 'rb') as f:
        if f.read(2) == BOM_UTF16_LE:
            return 'utf_16'
        return default if default else sys.getdefaultencoding()

with open(filename, encoding=get_file_encoding(filename, 'windows_1252')) as f:
    for line in f:
        for phrase in key_phrases: 
            if phrase in line:
                print(line)
                break 

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

Другие вопросы по теме