function IsTextUTF8(const Source: AnsiString): Boolean;
var
Chr: Byte;
I, Octets: Integer;
AllAscii: Boolean;
begin
if Source <> '' then
begin
Octets := 0;
AllAscii := True;
for I := 1 to Length(Source) do
begin
Chr := Byte(Source);
if Chr and $80 <> 0 then
AllAscii := False;
if Octets = 0 then
begin
if Chr >= $80 then
begin
repeat
Chr := Chr shl 1;
Inc(Octets);
until Chr and $80 = 0;
Dec(Octets);
if Octets = 0 then
begin
Result := False;
Exit;
end;
end;
end
else
begin
if Chr and $C0 <> $80 then
begin
Result := False;
Exit;
end;
Dec(Octets);
end;
end;
Result := (Octets <= 0) and not AllAscii;
end
else
Result := False;
end;
Определение кодировки читаемого файла
Вся проблема в том, что в зависимости от кодировки файла, к нему применяется или не применяется функция Utf8ToAnsi().
Соответственно нужно определить, когда эту функцию применять, а когда нет. Т.е. нужно что то вроде функции определения кодировки.
Есть ли такое в природе и если нет, то можно ли как сделать самому?
Первая идея была определять UTF-8 файл по наличию BOM, но есть UTF-8 файлы не содержащие BOM меток... Соответственно этот метод не подходит...
Считывайте все как UTF-8. У него полная обратная совместимость.
Utf8ToAnsi("Ascii строка") возвращает нулевой результат.
Цитата: Odissey_
Считывайте все как UTF-8. У него полная обратная совместимость.
С каких это пор? Хм. :)
Цитата: Gigahard
Т.е. нужно что то вроде функции определения кодировки.
Есть ли такое в природе и если нет, то можно ли как сделать самому?
Есть ли такое в природе и если нет, то можно ли как сделать самому?
Код:
Возможно, стоит занести в FAQ.
Подходя к вопросу с другой стороны... Вся эта затея с преобразованием utf8 в ascii в принципе нужна для корректного вывода на стандартные контролы... А они вроде как не понимают utf-8... Или все же понимают?
Код:
bool IsTextUTF8(AnsiString Source)
{
BYTE Chr;
int i, Octets;
bool AllAscii;
if (Source !="")
{
Octets= 0;
AllAscii= true;
for (i= 1; Source.Length(); i++)
{
Chr = Byte(Source);
if ((Chr & 0x80) != 0)
AllAscii = false;
if (Octets == 0)
{
if (Chr >= 0x80)
{
do
{
Chr= Chr << 1;
Octets++;
}
while((Chr & 0x80) == 0);
Octets--;
if (Octets == 0)
return false;
}
}
else
{
if((Chr & 0xC0) != 0x80)
{
return false;
}
Octets--;
}
}
return bool ((Octets <= 0) && !AllAscii);
}
return false;
}
{
BYTE Chr;
int i, Octets;
bool AllAscii;
if (Source !="")
{
Octets= 0;
AllAscii= true;
for (i= 1; Source.Length(); i++)
{
Chr = Byte(Source);
if ((Chr & 0x80) != 0)
AllAscii = false;
if (Octets == 0)
{
if (Chr >= 0x80)
{
do
{
Chr= Chr << 1;
Octets++;
}
while((Chr & 0x80) == 0);
Octets--;
if (Octets == 0)
return false;
}
}
else
{
if((Chr & 0xC0) != 0x80)
{
return false;
}
Octets--;
}
}
return bool ((Octets <= 0) && !AllAscii);
}
return false;
}
Единственная проблема, код не работает :(
И что то не могу я въехать в функционал кода... Как оно работает то?
Английский текст в UTF8 выглядит точно также как и cp866 и cp1251 и koi8-r. Есть определенная таблица частот встречаемости русских символов в предложениях, таким образом, чем больше текста, тем больше точность определения кодировки. Содержимое файла перекодируется во все доступные кодировки и сравнивается частота встречаемости букв, там где она выше, та кодировка и стоит. Соответственно для других языков нужные свои таблицы.
Цитата: Gigahard
И что то не могу я въехать в функционал кода... Как оно работает то?
UTF-8 отличается от приведённых SABROG-ом кодировок регулярностью встречающихся октетов, определяемой однозначно, что и делает функция.
Простой поиск в Google по имени функции вывел на китайцев. Обращаем внимание на комментарии в заголовке исходника - это микрочленовский Блокнот. Как функция заработает, Gigahard-у предложение открыть собственную компанию и назвать GigaSoft.
В общем проверку на UTF-8 сделал так:
Код:
AnsiString output;
if((strlen(tst)>0) && Utf8ToAnsi(tst)!="")
{
output= Utf8ToAnsi(tst);
Form1->Caption="UTF-8 Input";
}
else
{
output= tst;
Form1->Caption="ASCII Input";
}
if((strlen(tst)>0) && Utf8ToAnsi(tst)!="")
{
output= Utf8ToAnsi(tst);
Form1->Caption="UTF-8 Input";
}
else
{
output= tst;
Form1->Caption="ASCII Input";
}
tst здесь строка с исходным текстом.
Цитата: Gigahard
Как говориться, "Нормальные герои, всегда идут в обход..." :D
Все гениальное просто гы...
Однако стоило бы заморочиться с определением всех возможных кодировок по частоте букв...