Как лучше всего определить, может ли строка (есть или) быть закодирована в UTF-8? Win32 API IsTextUnicode здесь не особо помогает. Кроме того, в строке не будет спецификации UTF-8, поэтому ее нельзя будет проверить. И, да, я знаю, что только символы выше диапазона ASCII кодируются более чем 1 байтом.
Как определить строки в кодировке UTF-8
Ответы (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
Вы также можете взглянуть на соответствующий вопрос Как лучше всего угадать кодировку, когда отсутствует спецификация (метка порядка байтов)?, в ней есть полезное содержание.
Нет действительно надежного способа, но в основном случайная последовательность байтов (например, строка в стандартной 8-битной кодировке) вряд ли будет действительной строкой UTF-8 (если установлен самый старший бит байта, существуют очень конкретные правила относительно того, какие байты могут следовать ему в UTF-8), вы можете попробовать декодировать строку как UTF-8 и считать, что это UTF-8, если нет ошибок декодирования.
Определение наличия ошибок декодирования - это еще одна проблема, многие библиотеки Unicode просто заменяют недопустимые символы вопросительным знаком, не указывая, произошла ли ошибка. Поэтому вам нужен явный способ определения, произошла ли ошибка при декодировании или нет.
На этой странице W3C есть регулярное выражение Perl для проверки UTF- 8
Для 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);
Чтобы обнаружить символы в рубине, установите драгоценный камень chardet.
sudo gem install chardet
Вот небольшой скрипт на Ruby для запуска chardet поверх стандартного входного потока.
require "rubygems"
require 'UniversalDetector' #chardet gem
infile = $stdin.read()
p UniversalDetector::chardet(infile)
Chardet выводит предположение о кодировке набора символов, а также уровень достоверности (0-1) из своего статистического анализа.
см. также этот фрагмент < / а>
Автономная библиотека C / C ++ на основе детектора набора символов Mozilla
https://github.com/batterseapower/libcharsetdetect
Детектор универсального набора символов (UCSD) Библиотека, предоставляющая интерфейс C и интерфейс без зависимостей для библиотеки Mozilla C ++ UCSD. Эта библиотека предоставляет высокоточный набор эвристик, которые пытаются определить набор символов, используемый для кодирования некоторого входного текста. Это чрезвычайно полезно, когда ваша программа должна обрабатывать входной файл, который поставляется без каких-либо метаданных кодирования.
Вы не указали язык, но в PHP вы можете использовать mb_check_encoding
if(mb_check_encoding($yourDtring, 'UTF-8'))
{
//the string is UTF-8
}
else
{
//string is not UTF-8
}
В Windows вы можете использовать MultiByteToWideChar() с CP_UTF8 кодовой страницей и флагом MB_ERR_INVALID_CHARS. Если функция не работает, строка недопустима в кодировке UTF-8.
В качестве дополнения к предыдущему ответу об 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 с большой уверенностью!