-
kashey © (16.08.18 12:41) [0]Нагуглил вариант:
Если количество символов #$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]