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

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

На каком языке вы пытаетесь это сделать?

Martijn Laarman 18.12.2008 12:10

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

Johann Gerell 18.12.2008 12:13

И вы не найдете спецификации в начале потока UTF-8, это не имеет смысла, поскольку UTF-8 одинаков, независимо от порядка байтов.

mat 18.12.2008 12:38

Да, но некоторые по-прежнему называют его «спецификацией». Я предпочитаю называть это «преамбулой» (как .NET) или «подписью». Это все еще может быть полезно для идентификации кодировки.

Johann Gerell 18.12.2008 13:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
4
12 023
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

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

Любая библиотека Unicode правильный должна заменять неизвестные символы на U + FFFD, а не с буквальным знаком вопроса.

tripleee 15.12.2020 11:28

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

Если вы читаете поток и у вас может не быть начала, вам следует либо потерять \ A в начале, либо добавить ". {0,5}?" сразу после него, чтобы захватить первый усеченный символ.

mat 18.12.2008 12:27

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

Laurent 18.12.2008 12:38
Ответ принят как подходящий

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

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

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

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

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

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

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

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

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

Извините, что комментирую ответ 10-летней давности, но у меня есть небольшая поправка. cpdetector не является библиотекой Delphi (написан на Java). Если кто-то ищет определение кодировки Delphi, возможно, стоит изучить чсдет.

Adam Henderson 20.03.2018 13:42

@AdamHenderson спасибо за исправление, я обновил вопрос

Edward Wilde 30.05.2018 20:03

Для обнаружения символов в рубине установите гем '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

Universal Character Set Detector (UCSD) A library exposing a C interface and dependency-free interface to the Mozilla C++ UCSD library. This library provides a highly accurate set of heuristics that attempt to determine the character set used to encode some input text. This is extremely useful when your program has to handle an input file which is supplied without any encoding metadata.

Вы не указали язык, но в 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 вы можете использовать API mlang, это часть 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);

Я только что провел несколько тестов подпрограммы DetectEncodingInfo (), и результаты очень плохие: * Он не может различать французские тексты в CP 437 и CP 1252, даже если текст полностью нечитаем, если открыть в неправильном кодовая страница. * Он может обнаруживать текст, закодированный в CP 65001 (UTF-8), но не текст в UTF-16, который ошибочно сообщается как CP 1252 с большой уверенностью!

Jean-François Larvoire 11.05.2020 12:03

В качестве дополнения к предыдущему отвечать о 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 с большой уверенностью!

Этот код на самом деле не компилируется.

JeffR 10.02.2021 16:00

Конечно, необходим минимальный код. Вы должны интегрировать в свою собственную действующую функцию.

Jean-François Larvoire 11.02.2021 16:02

Другие вопросы по теме