Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

определить UTF8 без BOM


kashey ©   (16.08.18 12:41

Нагуглил вариант:

Если количество символов #$D0, #$D1 превышает треть от количества остальных символов с кодами >127, то это с очень высокой вероятностью UTF-8.


Но правильно срабатывает не всегда. Понятно что 100% алгоритма нет, но хотелось бы что-то понадежней, тот-же Notepad++ чтобы ошибался в кодировке, пока не наблюдал.
Наверняка есть варианты получше моего. Просвятите пожалуйста кто знает.


Inovet ©   (16.08.18 12:47[1]

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


kashey ©   (16.08.18 12:58[2]

Этот вариант нагуглили на DelphiKingdom::ответ Python

Первый вариант. Если количество символов #$D0, #$D1 превышает треть от количества остальных символов с кодами >127, то это с очень высокой вероятностью UTF-8.

Второй вариант - пытаться декодировать файл в кодировке UTF-8, если символов с кодами >127 не найдено - это точно не UTF-8, а если ошибок не было - то точно UTF-8 (если есть ошибки - принимать решение, 1-2 ошибки на десятки тысяч символов - это можно игнорировать).


Я вообще не въехал как реализовать второй вариант, ну хотя бы >>пытаться декодировать файл в кодировке UTF-8. Если я заведомо не могу знать в какой он кодировке.


Inovet ©   (16.08.18 13:23[3]

> [2] kashey ©   (16.08.18 12:58)

Ключевое слово - пытаться.


RWolf ©   (16.08.18 14:18[4]

Байты $80 и выше в текстовом файле UTF-8 подчиняются определённым правилам, см. алгоритм кодирования символов в UTF-8. Соответственно, если в файле такие байты есть, но правила не соблюдаются, это наверняка не UTF-8.


Styx ©   (16.08.18 15:18[5]


> тот-же Notepad++ чтобы ошибался в кодировке, пока не наблюдал.

Дык смотрите исходники: https://github.com/notepad-plus-plus/notepad-plus-plus


kashey ©   (16.08.18 15:27[6]


> Второй вариант - пытаться декодировать файл в кодировке
> UTF-8, если символов с кодами >127 не найдено - это точно
> не UTF-8, а если ошибок не было - то точно UTF-8 (если есть
> ошибки - принимать решение, 1-2 ошибки на десятки тысяч
> символов - это можно игнорировать).
>


Пытался выразить это в коде, но видать не то:

   err_count := 0;
   sumb127 := 0;
   for i := 0 to FStringList.Count - 1 do begin
     try
       bufs := UTF8Decode(FStringList[i]);
       for j := 1 to Length(bufs) do begin
         if Ord(bufs[j]) > 127 then Inc(sumb127);
       end;
     except
       Inc(err_count);
     end;
   end;

   if sumb127 = 0 then begin
     ShowMessage('Точно не UTF-8');
   end
   else if err_count = 0 then begin
     ShowMessage('Точно UTF-8');
   end
   else if (Length(FStringList.Text) / err_count) > 2000 then begin
     ShowMessage('Скорее всего UTF-8');
   end
   else begin
     ShowMessage('Другая кодировка');
   end;


kashey ©   (16.08.18 15:29[7]


> Дык смотрите исходники: https://github.com/notepad-plus-
> plus/notepad-plus-plus

В этом ворохе файлов попробуй найди то что надо.


kashey ©   (16.08.18 15:48[8]

А кажись нашел, но как эту жуткую кракозябру перевести на нормальный язык


namespace Utf8 { // could be a static class, instead of a namespace, if it needs private members
// basic classification of UTF-8 bytes
inline static bool isSingleByte(UCHAR c)       { return c < 0x80; }
inline static bool isPartOfMultibyte(UCHAR c)  { return c >= 0x80; }
inline static bool isFirstOfMultibyte(UCHAR c) { return c >= 0xC2 && c < 0xF5; } // 0xF5 to 0xFD are defined by UTF-8, but are not currently valid Unicode
inline static bool isContinuation(UCHAR c)     { return (c & 0xC0) == 0x80; }
inline static bool isValid(UCHAR c)            { return c < 0xC0 || isFirstOfMultibyte(c); } // validates a byte, out of context

// number of continuation bytes for a given valid first character (0 for single byte characters)
inline static int  continuationBytes(UCHAR c)  {
 static const char _len[] = { 1,1,2,3 };
 return (c < 0xC0) ? 0 : _len[(c & 0x30) >>  4];
}

// validates a full character
inline static bool isValid(const char* buf, int buflen) {
 if(isSingleByte(buf[0])) return true; // single byte is valid
 if(!isFirstOfMultibyte(buf[0])) return false; // not single byte, nor valid multi-byte first byte
 int charContinuationBytes = continuationBytes(buf[0]);
 if(buflen < charContinuationBytes+1) return false; // character does not fit in buffer
 for(int i = charContinuationBytes; i>0; --i)
  if(!isContinuation(*(++buf))) return false; // not enough continuation bytes
 return true;  // the character is valid (if there are too many continuation bytes, it is the next character that will be invalid)
}

// rewinds to the first byte of a multi-byte character for any valid UTF-8 (and will not rewind too much on any other input)
inline static int characterStart(const char* buf, int startingIndex) {
 int charContinuationBytes = 0;
 while(charContinuationBytes < startingIndex // rewind past start of buffer?
  && charContinuationBytes < 5 // UTF-8 support up to 5 continuation bytes (but valid sequences currently do not have more than 3)
  && isContinuation(buf[startingIndex-charContinuationBytes])
  )
  ++charContinuationBytes;
 return startingIndex-charContinuationBytes;
}
};


Styx ©   (16.08.18 16:01[9]


> В этом ворохе файлов попробуй найди то что надо.

Где-то здесь: https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/PowerEditor/src/uchardet/README.TXT

Uchardet is a C language binding of the original C++ implementation of the universal charset detection library by Mozilla.
The source code of universalchardet is available at https://github.com/BYVoid/uchardet

Текущая версия библиотеки здесь: https://www.freedesktop.org/wiki/Software/uchardet/


DayGaykin ©   (16.08.18 17:32[10]


> если символов с кодами >127 не найдено - это точно не UTF-
> 8

Еще какой UTF8.

Однозначно не определишь.


kashey ©   (16.08.18 17:42[11]

Кучу готовый примеров на Си нагуглил и не одного Delphi. Плохо искал? Попытаюся переписать с Си.


Styx ©   (16.08.18 18:07[12]

Плохо. Вот, нашёлся за 2 секунды: https://sourceforge.net/projects/chsdet/files/chsdet/0.2/chsdet_026_src.zip/download
Что внутри - не смотрел :)


kashey ©   (16.08.18 18:13[13]


> Что внутри - не смотрел :)

Ну да может вирусяка )


Styx ©   (16.08.18 18:20[14]

Это исходники жеж :)


aka ©   (16.08.18 19:50[15]

http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.WideStrUtils.IsUTF8String


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо