Как читать как из кодированных в ANSI, так и в Юникоде файлов в Python - PullRequest
0 голосов
/ 01 июня 2018

Я пытаюсь написать функцию, используя 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.")

1 Ответ

0 голосов
/ 03 июня 2018

В файлах, закодированных в 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 

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

...