Вопрос по character-encoding, ide, utf-8 – Определить кодировку UTF-8 (как это делает MS IDE)?

6

Проблема с различными кодировками символов заключается в том, что содержащийся файл не всегда четко обозначен. Существуют противоречивые соглашения для маркировки некоторых с использованием «меток порядка следования байтов». или спецификации. Но по сути вы должны бытьtold что такое кодировка файла, чтобы прочитать его точно.

Мы создаем инструменты программирования, которые читают исходные файлы, и это дает нам горе. У нас есть средства для определения значений по умолчанию, сниффинга для спецификаций и т. Д. И мы довольно хорошо справляемся с соглашениями и значениями по умолчанию. Но место, где мы (и я полагаю, все остальные) зацикливаются на файлах UTF-8, которые не помечены как BOM.

Последние MS IDE (например, VS Studio 2010), по-видимому, будут "нюхать" файл, чтобы определить, закодирован ли он в кодировке UTF-8 без спецификации. (Находясь в сфере инструментов, мы хотели бы быть совместимыми с MS из-за их доли на рынке, даже если это означает необходимость пересекать с ними «тупой» утес.) Я особенно заинтересован в том, что они используют как эвристика (хотя обсуждение эвристики в порядке)? Как это может быть "правильно"? (Рассмотрим строку в кодировке ISO8859-x, интерпретированную таким образом).

РЕДАКТИРОВАТЬ: Эта статья об обнаружении кодировок / наборов символов довольно интересна: http://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html

РЕДАКТИРОВАТЬ Декабрь 2012: Мы прекратили сканирование всего файла, чтобы увидеть, нет ли в нем каких-либо нарушений последовательностей UTF-8 ... и если нет, мы называем его UTF-8. Плохая часть этого решения заключается в том, что вам придется обрабатывать символы дважды, если это UTF-8. (Если это не UTF-8, этот тест, скорее всего, определит это довольно быстро, если только файл не встречается со всеми 7-битными ASCII, в которых чтение, такое как UTF-8, не повредит).

Попытка прочитать весь файл как UTF-8 будет либо «успешной» или встретить недопустимые последовательности байтов. В какой-то момент мне показалось, что я увидел статью, рассказывающую о вероятности ложных срабатываний, но я не могу переместить ее. user166390
Ни один файл ISO-8859-x, в котором когда-либо есть один не-ASCII-символ, окруженный ASCII, никогда не будет действительным UTF-8. Большинство двухбайтовых последовательностей, отличных от ASCII, не являются действительными UTF-8. Есть несколько примеров реальных строк, которые могут быть неверно истолкованы как UTF-8, но вряд ли для всего файла будут иметь только эти строки. prosfilaes
Это ответ (stackoverflow.com/a/4522251/120163) утверждает что-то крошечное "ложноположительное" ставка на довольно короткие последовательности символов. Я пытаюсь решить, понимаю ли я / верю этому. Ira Baxter
Если вы можете обработать весь файл, почему бы не проверить его на правильность кодировки utf-8? Если это так, то, скорее всего, это действительно utf-8. Nickolay Olshevsky
... приведенный выше ответ, по-видимому, предполагает случайное, плоское распределение символов, взятых из набора Unicode, которое я очень подозреваю в неправильности, поэтому я прихожу к выводу, что аргументы в пользу крошечных ложных срабатываний неверны. (Это может все еще быть крошечным). Ira Baxter

Ваш Ответ

2   ответа
1

По сути, когда вы не знаете кодировку файла / потока / источника, вам необходимо проверить весь файл и / или найти фрагменты текста, чтобы убедиться, что вы получаете совпадения UTF-8. Я вижу, что это похоже на то, что делают некоторые антивирусные продукты, проверяя части известных вирусных подстрок

Возможно, я бы посоветовал вам применить вызов к функции, аналогичной той, которую мы делали при чтении файла / потока, построчно, чтобы определить, найдена ли кодировка UTF-8 или нет

Пожалуйста, обратитесь к нашему сообщению ниже

Ref. - https://stackoverflow.com/questions/17283872/how-to-detect-utf-8-based-encoded-strings

По сути, вы не можете выиграть эту войну. Поскольку некоторые битовые строки могут быть как в формате UTF-8, так и в формате EBCDIC, единственный способ, которым вы можете на самом деле знать, - это сказать. Есть два способа сказать: 1) метаданные вне тестового контейнера (легко и часто теряются) и 2) метаданные, помечающие файл (спецификация и т. Д. Или атрибуты файла). Но люди, похоже, ненавидят маркеры в стиле спецификации. То, что осталось, это хаос, который есть у нас, и заслуженный как сообщество. IQ, по-видимому, не является аддитивным. Ira Baxter
Кроме того, мы обнаружили, что недостаточно надежно просто определить кодировку файла, либо прочитав его заголовок спецификации, либо проверив его объявление UTF-8 в случае HTML, то есть вы могли бы читать из базы данных и не знаете, это UTF или нет, то же самое применимо, если кто-то просто копирует / вставляет текст в текстовое поле или текстовое поле, и ваша кодировка специально не ожидала / не кодировала для хранения данных на основе UTF. Я надеюсь, что функция, которую мы сделали в нашем посте, поможет другим. С уважением, Диего
Так что вы предлагаете? Потому что, в конце концов, нам всем приходится иметь дело со строкой, которую мы «не знаем». источнику и / или не сообщается, в какой кодировке он находится. Задавая себе этот вопрос я, почему я пришел к этой функции. Я знаю, что он эффективно обнаруживает знаки препинания и символы в большинстве распространенных языков, я не могу гарантировать, что он сможет обнаружить другие действительно необычные символы, но & # xE1; & # xE9; & # xED; & # xF3; & # xFA ;, basic & # xE0; & # xE8; & # xEC; & # xF2; & # xF9 ;, & # xE4; & # xEB; & # xEF; & # xF6; & # xFC; и другие, а также символы обнаруживаются моей функцией. Я понимаю вашу точку зрения, но есть кое-что, что мы должны сделать или, по крайней мере, полагаться на обходной путь
Вы не внимательно прочитали мою заметку РЕДАКТИРОВАТЬ в декабре 2012 г. Это именно то, что я сказал, и мы сделали. Вы не можете обрабатывать порции; Вы можете обработать все это, чтобы решить. (Что означает читать его построчно, если вы еще не определили кодировку?) Ira Baxter
Хорошо, что вы сделали то же самое, что и мы, и то, что мы объясняем в нашем посте. Причина чтения по частям зависит от использования; то есть, если я делаю скребок и мне нужно отображать части того, что я скребу, в виде списка, мне не нужно обнаруживать весь очищенный HTML, который я получаю, а только ту часть текста, которую я хочу отобразить в сетке / элементе управления. Необходимость использовать функцию, подобную той, что мы сделали, заключается в том, что вы не можете UTF-декодировать то, что уже UTF-декодировано. т.е. DecodeUTF8 (& quot; Societ & # xE9; & quot;) будет возвращать что-то вроде Societ & # xBF; что неправильно. Вот почему вам сначала нужно определить, является ли строка Societ & # xC3; & # x2C6;
6

первый символ, который вы видите более 0x7F, должен быть началом последовательности UTF-8. Так что проверь это. Вот код, который мы используем для этого:

unc ::IsUTF8(unc *cpt)
{
    if (!cpt)
        return 0;

    if ((*cpt & 0xF8) == 0xF0) { // start of 4-byte sequence
        if (((*(cpt + 1) & 0xC0) == 0x80)
         && ((*(cpt + 2) & 0xC0) == 0x80)
         && ((*(cpt + 3) & 0xC0) == 0x80))
            return 4;
    }
    else if ((*cpt & 0xF0) == 0xE0) { // start of 3-byte sequence
        if (((*(cpt + 1) & 0xC0) == 0x80)
         && ((*(cpt + 2) & 0xC0) == 0x80))
            return 3;
    }
    else if ((*cpt & 0xE0) == 0xC0) { // start of 2-byte sequence
        if ((*(cpt + 1) & 0xC0) == 0x80)
            return 2;
    }
    return 0;
}

Если вы получаете возврат 0, это не является действительным UTF-8. В противном случае пропустите количество возвращаемых символов и продолжайте проверять следующий по 0x7F.

Вы не ответили на вопрос о том, что делает MS, но я подозреваю, что я вряд ли получу ответ. Вы предоставили простой механизм проверки. Я не думаю, что он завершен, потому что он будет принимать некоторые не-Unicode последовательности (не все комбинации действительны), но он довольно хорош в качестве hueristic. Итак, я даю вашему ответу выгоду. Ira Baxter
Мы сделали что-то по существу эквивалентное этому. Спасибо за подробный ответ, хотя. Ira Baxter
@ Джереми Гриффит I конвертер в методе JavaisUTF at this way == & GT; В результате эта часть не работает, если ((buffer [0] & amp; 0xF8) == 0xF0) {(и currenttaFile 100% с хорошим кодированием) Почему это происходит? Что случилось? Как решить эту проблему?
Я бы добавил четвертый случай для простого ascii:else if (*cpt & 0x80 == 0x00) return 1;

Похожие вопросы