Как определить строки в кодировке UTF-8

Как лучше всего определить, может ли строка (есть или) быть закодирована в UTF-8? Win32 API IsTextUnicode здесь не особо помогает. Кроме того, в строке не будет спецификации UTF-8, поэтому ее нельзя будет проверить. И, да, я знаю, что только символы выше диапазона ASCII кодируются более чем 1 байтом.


person Johann Gerell    schedule 18.12.2008    source источник
comment
На каком языке вы пытаетесь это сделать?   -  person Martijn Laarman    schedule 18.12.2008
comment
Ничего особенного - ищу общий метод. Но если вы можете дать что-то, что работает для определенного языка, пожалуйста, присоединяйтесь.   -  person Johann Gerell    schedule 18.12.2008
comment
И вы не найдете спецификации в начале потока UTF-8, это не имеет смысла, поскольку UTF-8 одинаков, независимо от порядка байтов.   -  person mat    schedule 18.12.2008
comment
Да, но некоторые до сих пор называют это спецификацией. Я предпочитаю называть это преамбулой (как .NET) или подписью. Это все еще может быть полезно для идентификации кодировки.   -  person Johann Gerell    schedule 18.12.2008


Ответы (9)


Обнаружение набора символов chardet, разработанного Mozilla и используемого в FireFox. Исходный код

jchardet - это java-порт источника из алгоритма автоматического определения кодировки Mozilla.

NCharDet - это порт .Net (C #) порта Java для C ++, используемого в Браузеры Mozilla и FireFox.

Пример C # проекта кода, в котором используется MLang для определения кодировки символов.

UTRAC - это инструмент и библиотека командной строки, написанная на C ++ для определения кодировки строк.

cpdetector - это Java-проект, используемый для обнаружения кодировки.

chsdet - это проект delphi и отдельный исполняемый модуль для автоматического определения кодировки / кодировки заданного текста. или файл.

Еще один полезный пост, который указывает на множество библиотек, которые помогут вам определить кодировку символов http://fredeaker.blogspot.com/2007/01/character-encoding-detection.html

Вы также можете взглянуть на соответствующий вопрос Как лучше всего угадать кодировку, когда отсутствует спецификация (метка порядка байтов)?, в ней есть полезное содержание.

person Edward Wilde    schedule 18.12.2008
comment
Извините, что комментирую ответ 10-летней давности, но у меня есть небольшая поправка. cpdetector - это не библиотека Delphi (написана на Java). Если кто-то ищет определение кодировки Delphi, возможно, стоит изучить chsdet. - person Adam Henderson; 20.03.2018
comment
@AdamHenderson спасибо за исправление, я обновил вопрос - person Edward Wilde; 30.05.2018

Нет действительно надежного способа, но в основном случайная последовательность байтов (например, строка в стандартной 8-битной кодировке) вряд ли будет действительной строкой UTF-8 (если установлен самый старший бит байта, существуют очень конкретные правила относительно того, какие байты могут следовать ему в UTF-8), вы можете попробовать декодировать строку как UTF-8 и считать, что это UTF-8, если нет ошибок декодирования.

Определение наличия ошибок декодирования - это еще одна проблема, многие библиотеки Unicode просто заменяют недопустимые символы вопросительным знаком, не указывая, произошла ли ошибка. Поэтому вам нужен явный способ определения, произошла ли ошибка при декодировании или нет.

person Laurent    schedule 18.12.2008
comment
Любая правильная библиотека Unicode должна заменять неизвестные символы на U + FFFD, без буквального знака вопроса. - person tripleee; 15.12.2020

На этой странице W3C есть регулярное выражение Perl для проверки UTF- 8

person hamishmcn    schedule 18.12.2008
comment
Если вы читаете поток и у вас может не быть начала, вам следует либо потерять \ A в начале, либо добавить. {0,5}? сразу после него, чтобы захватить первый усеченный символ. - person mat; 18.12.2008
comment
Я бы порекомендовал сделать это, используя стандартную библиотеку Unicode языка вместо того, чтобы повторно реализовывать ее с помощью регулярных выражений. - person Laurent; 18.12.2008

Для Win32 вы можете использовать mlang API, это часть Windows и поддерживается в Windows XP. Интересно то, что он дает вам статистику того, насколько вероятно, что ввод будет в определенной кодировке:

CComPtr<IMultiLanguage2> lang;
HRESULT hr = lang.CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER);
char* str = "abc"; // EF BB BF 61 62 63
int size = 6;
DetectEncodingInfo encodings[100];
int encodingsCount = 100;
hr = lang->DetectInputCodepage(MLDETECTCP_NONE, 0, str, &size, &encodings, &encodingsCount);
person Community    schedule 11.10.2013
comment
Я только что провел несколько тестов подпрограммы DetectEncodingInfo (), и результаты очень плохие: * Он не может различать французские тексты в CP 437 и CP 1252, даже если текст полностью нечитаем, если открыть в неправильном кодовая страница. * Он может обнаруживать текст, закодированный в CP 65001 (UTF-8), но не текст в UTF-16, который ошибочно сообщается как CP 1252 с хорошей уверенностью! - person Jean-François Larvoire; 11.05.2020

Чтобы обнаружить символы в рубине, установите драгоценный камень chardet.

sudo gem install chardet

Вот небольшой скрипт на Ruby для запуска chardet поверх стандартного входного потока.

require "rubygems"
require 'UniversalDetector' #chardet gem
infile =  $stdin.read()
p UniversalDetector::chardet(infile)

Chardet выводит предположение о кодировке набора символов, а также уровень достоверности (0-1) из своего статистического анализа.

см. также этот фрагмент < / а>

person Harry Wood    schedule 18.07.2011

Автономная библиотека C / C ++ на основе детектора набора символов Mozilla

https://github.com/batterseapower/libcharsetdetect

Детектор универсального набора символов (UCSD) Библиотека, предоставляющая интерфейс C и интерфейс без зависимостей для библиотеки Mozilla C ++ UCSD. Эта библиотека предоставляет высокоточный набор эвристик, которые пытаются определить набор символов, используемый для кодирования некоторого входного текста. Это чрезвычайно полезно, когда ваша программа должна обрабатывать входной файл, который поставляется без каких-либо метаданных кодирования.

person Tom    schedule 21.06.2012

Вы не указали язык, но в PHP вы можете использовать mb_check_encoding

   if(mb_check_encoding($yourDtring, 'UTF-8'))
   {
   //the string is UTF-8
    }
   else 
    {
       //string is not UTF-8
     }
person Ryan    schedule 21.06.2012

В Windows вы можете использовать MultiByteToWideChar() с CP_UTF8 кодовой страницей и флагом MB_ERR_INVALID_CHARS. Если функция не работает, строка недопустима в кодировке UTF-8.

person Remy Lebeau    schedule 21.06.2012

В качестве дополнения к предыдущему ответу об Win32 mlang DetectInputCodepage () API, вот как вызвать его на C:

#include <Mlang.h>
#include <objbase.h>
#pragma comment(lib, "ole32.lib")

HRESULT hr;
IMultiLanguage2 *pML;
char *pszBuffer;
int iSize;
DetectEncodingInfo lpInfo[10];
int iCount = sizeof(lpInfo) / sizeof(DetectEncodingInfo);

hr = CoInitialize(NULL);
hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMultiLanguage2, (LPVOID *)&pML);
hr = pML->lpVtbl->DetectInputCodepage(pML, 0, 0, pszBuffer, &iSize, lpInfo, &iCount);

CoUninitialize();

Но результаты тестов очень неутешительные:

  • Он не может различить французские тексты в CP 437 и CP 1252, даже если текст полностью нечитаем, если открыть его на неправильной кодовой странице.
  • Он может обнаруживать текст, закодированный в CP 65001 (UTF-8), но не текст в UTF-16, который ошибочно сообщается как CP 1252 с большой уверенностью!
person Jean-François Larvoire    schedule 11.05.2020
comment
Этот код на самом деле не компилируется. - person JeffR; 10.02.2021
comment
Конечно, необходим минимальный код. Вы должны интегрировать в свою собственную действующую функцию. - person Jean-François Larvoire; 11.02.2021