Нечувствительный к регистру текстовый поиск внутри двоичных данных в macOS - PullRequest
1 голос
/ 28 апреля 2019

Я пытаюсь реализовать возможность поиска текста в файлах, которые нельзя загрузить в строку NSString.

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

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

Единственное предположение, которое я делаю, заключается в том, что текст, который я хочу найти, использует кодировку UTF-8 (т.е. мне не нужно иметь дело с UTF-16).Если файл на самом деле закодирован в MacRoman, и я ищу не-ASCII-символы (набор 8-х бит), для этого не нужно искать совпадение.

Здесь я пытаюсь обойти то, что NSString можетне загружать некоторые «плохо» закодированные файлы, и я все еще хотел бы найти что-нибудь вокруг плохих символов.

Поиск должен быть нечувствителен к:

  • case (высший приоритет)
  • диакритические знаки (низкий приоритет)
  • юникодная композиция (низкий приоритет)

Другая цель - быть быстрым.Это для утилиты поиска файлов, которая может просматривать тысячи больших файлов.

Так как я не могу загрузить данные в строку NSStt, мне нужно использовать другие API поиска.

Какие опции делаютЯ имею?Существуют ли библиотеки, которые могут это сделать, то есть найти текст, пропуская плохие символы?

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


Примечание: я пытался преобразовать такие данные в строку NSString с

[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]

и с

[NSString stringEncodingForData:data encodingOptions:@{
        NSStringEncodingDetectionAllowLossyKey: @YES,
        NSStringEncodingDetectionLossySubstitutionKey: @" ",
        NSStringEncodingDetectionUseOnlySuggestedEncodingsKey: @YES,
        NSStringEncodingDetectionSuggestedEncodingsKey: @[@(NSASCIIStringEncoding)]
    }
    convertedString:&text usedLossyConversion:nil
];

В то время как оба, кажется, сначала работают, это приводит к случайной панике ядра или другим серьезным сбоям, когда я вызываю -[NSString localizedStandardContainsString] и подобные функции поиска.Когда он не падает, он работает довольно хорошо.

Эти сбои появляются на моем 10.13.6, чего мне достаточно, чтобы избежать этой техники, даже если Apple исправила это в 10.14.3.

1 Ответ

0 голосов
/ 28 апреля 2019

Я придумал решение, которое не очень элегантно и может быть весьма неэффективным.

Я пытаюсь использовать предоставляемую системой библиотеку регулярных выражений.Проблема в том, что он неправильно обрабатывает различные вещи, которые хорошо выполняются операциями поиска NSString:

  • Они не разбираются в нормализации, т. Е. Если я ищу предварительно составленный (NFC) символ, он выиграет 'найти символ, если он встречается в разложенной (NFD) форме в целевых данных.
  • Поиск без учета регистра не работает для латинских символов NFC (поиск Ü не находит ü), но только для букв ASCII (az).

Я думаю, что при использовании интеллектуальных алгоритмов поиска, таких как Aho-Corasick , может быть сгенерировано удобное для поиска в Юникоде дерево поиска, которое учитывает все варианты не-Ассийский персонаж.Но это не так.

Итак, я подумал, что помогу регулярному выражению во всех этих вариациях, построив строку поиска регулярного выражения, которая содержит их все в виде групп, разделенных |.

Я мог бы убедиться, что этот алгоритм работает с латинскими символами, но не знаю, будет ли он работать и с другими сценариями, такими как китайский, где я считаю, что есть также варианты нормализации.

Код довольно длинный,поэтому я обобщу алгоритм здесь.Я разместил код здесь .

  • Я преобразую строку поиска в форму NFC.
  • Я смотрю на каждый символ в строке поиска.
  • Если код символа <128, то сохраните его таким образом. </li>
  • Char> = 128 проверяются на наличие различных прописных / строчных представлений.Если они это сделают, я создаю две альтернативные строки поиска для каждой.
  • Я получаю одну или несколько строк поиска.
  • Теперь я преобразую каждую строку поиска в форму NFC и NFD, добавляя тем самымбольше вариантов.
  • Наконец, я экранирую каждую строку для использования с регулярным выражением и объединяю их все с помощью "|"в качестве разделителя.

Например, строка поиска ä преобразуется в \ä|\Ä|\ä|\Ä с ä и Ä с использованием представлений NFC и NFD.В двоичном виде строка выглядит так:

5C C3 A4 7C 5C C3 84 7C 5C 61 CC 88 7C 5C 41 CC 88
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...