Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.02.14;
Скачать: CL | DM;

Вниз

UTF-8   Найти похожие ветки 

 
ford ©   (2009-11-27 13:27) [0]

Здравствуйте!
как на дельфи автоматически определить, что текст в кодировке UTF-8 ?
в инете нашел что есть такая славная функция
как function DetectUTF8Encoding(const s : UTF8String): TEncodeType;
в модуле WideStrUtils.pas

но в своем Delphi 7
я такого модуля не нашел :(


 
Игорь Шевченко ©   (2009-11-27 13:36) [1]


> как на дельфи автоматически определить, что текст в кодировке
> UTF-8


никак


 
ford ©   (2009-11-27 13:47) [2]

ну почему никак ....
я вот написал такую функцию
Function UTF8Check(src:TStrings):Boolean;
var i,j,RCount,ACount:Integer;
   s:String;
Begin
RCount:=0; ACount:=0;
for i:=0 to src.Count-1 do
 Begin
  s:=src[i];
  for j:=1 to Length(s) do
   Begin
    Inc(ACount);
    if (Ord(s[j])>=192) and (Ord(s[j])<=255) Then Inc(RCount);
   End;
 end;
if ((rCount*100)/acount)<20 Then result:=true
Else result:=false;
End;


в принципе определяется что там UTF8
хотя конечно это не 100%
но работает

а вот подскажите, я поставил менее 20% должны встречаться русские букавки :) честно, поставил от балды, может кто подскажет какой процент наличия русских букв относительно всего текста может с более менее нормальной долей вероятности сказать что этот текст в utf8 ?
понятно что моя функция на тексте
"privet vasya" выдаст что это UTF8 :( может что то еще нужно проверять не просто что это английские буквы а еще и что много "P" и "?" ?


 
clickmaker ©   (2009-11-27 13:49) [3]

на паскаль сам переводи

BOOL IsUTF8(LPBYTE pbBuff, LONG cb)
{
BOOL fASCII;
int i, nb, curr;
BYTE b;

BOOL result = FALSE;
if (cb == 0) return result;

fASCII = TRUE;
curr = 0;
while (curr < cb)
{
 nb = 0;
 b = pbBuff[curr];
 if ((b & 0x80) != 0)
 {
  fASCII = FALSE;
  if ((b & 0xc0) == 0x80) return result;
  else if ((b & 0xe0) == 0xc0) nb = 1;
  else if ((b & 0xf0) == 0xe0) nb = 2;
  else if ((b & 0xf8) == 0xf0) nb = 3;
  else if ((b & 0xfc) == 0xf8) nb = 4;
  else if ((b & 0xfe) == 0xfc) nb = 5;
  else return result;

  if (curr + nb >= cb) return result;

  for (i = 1; i <= nb; i++)
  {
   if ((pbBuff[i + curr] & 0xC0) != 0x80) return result;
  }
 }
 curr += nb + 1;
}
result = !fASCII;
return result;
}


 
ford ©   (2009-11-27 14:10) [4]

а пояснить логику можно??


 
Медвежонок Пятачок ©   (2009-11-27 14:17) [5]

Решение в лоб.

var s : string;
begin
s := "мама мыла раму";
//s := AnsiToUtf8(s);
if AnsiToUtf8(Utf8ToAnsi(s)) <> s then ShowMessage("Либо не в утф, либо нет не-анси символов")


 
clickmaker ©   (2009-11-27 14:31) [6]

> [4] ford ©   (27.11.09 14:10)
> а пояснить логику можно??

логика там несложная.
в утф-8 каждый символ может занимать от 1 до 6 байт. Если значение байта лежит за пределами кодировки ascii ((b & 0x80) != 0), то проверяем значение на совпадение с некими масками, которые с достаточной долей вероятности говорят о том, что это утф.
При этом в каждом байте также установлены биты, которые говорят, что этот байт не является последним (nb = 1...nb = 5).


 
ford ©   (2009-11-27 16:04) [7]


> Решение в лоб.

прикольное решение
для больших текстов не подходит но для маленьких вполне :)


> clickmaker ©   (27.11.09 14:31) [6]


спасибо, теперь понятно что там делается :)


 
Омлет ©   (2009-11-30 18:20) [8]

> [7] ford ©   (27.11.09 16:04)
> для больших текстов не подходит но для маленьких вполне

Бери маленький кусок большого текста.


 
Евгений471   (2009-12-14 11:37) [9]


> while (curr < cb) {  nb = 0;  b = pbBuff[curr];  if ((b
> & 0x80) != 0)  {   fASCII = FALSE;   if ((b & 0xc0) == 0x80)
> return result;   else if ((b & 0xe0) == 0xc0) nb = 1;   else
> if ((b & 0xf0) == 0xe0) nb = 2;   else if ((b & 0xf8) ==
> 0xf0) nb = 3;   else if ((b & 0xfc) == 0xf8) nb = 4;   else
> if ((b & 0xfe) == 0xfc) nb = 5;   else return result;   if
> (curr + nb >= cb) return result;   for (i = 1; i <= nb;
> i++)   {    if ((pbBuff[i + curr] & 0xC0) != 0x80) return
> result;   }  }  curr += nb + 1; } result = !fASCII;


на pascal

function TEncodeClass.FromString(const index: integer;
 const s: string): char;
begin
if (index <= 0) or (index > length(s)) then
begin
 Result := #0;
 exit;
end;
Result := s[index];
end;

function TEncodeClass.IsUtf8(const s: string; const cb:cardinal): boolean;
var
 fASCII:boolean;
 i, nb, curr:integer;
 b:byte;
begin
Result := false;
if cb<=0 then exit;
fASCII := TRUE;
curr   := 1;
while (curr < cb) do
begin          
 nb := 0;
 b  :=  ord(FromString(curr,s));
 if (b and StrToInt64("0x80")) <> 0 then
 begin
  fASCII := FALSE;
  if (b and StrToInt64("0xc0")) = StrToInt64("0x80") then exit else
  if (b and StrToInt64("0xe0")) = StrToInt64("0xc0") then nb := 1 else
  if (b and StrToInt64("0xf0")) = StrToInt64("0xe0") then nb := 2 else
  if (b and StrToInt64("0xf8")) = StrToInt64("0xf0") then nb := 3 else
  if (b and StrToInt64("0xfc")) = StrToInt64("0xf8") then nb := 4 else
  if (b and StrToInt64("0xfe")) = StrToInt64("0xfc") then nb := 5 else exit;
  if curr + nb >= cb then exit;
  for i := 1 to nb do
  if (ord(FromString(i+curr,s)) and StrToInt64("0xC0")) <> StrToInt64("0x80") then exit;
 end;
 inc(curr,nb+1);
end;
Result := not fASCII;
end;


 
clickmaker ©   (2009-12-14 11:43) [10]

> (b and StrToInt64("0xc0")) = StrToInt64("0x80")

что это??


 
Евгений471   (2009-12-14 14:57) [11]


> > (b and StrToInt64("0xc0")) = StrToInt64("0x80")что это?
> ?

> StrToInt64("0x80")
числа в 16-ти ричной системе - коды символов.
просто перевел код с C  на pascal без изминений, лень было писать коды символов в оригенальном значении.

вот этот код:

BOOL IsUTF8(LPBYTE pbBuff, LONG cb)
{
BOOL fASCII;
int i, nb, curr;
BYTE b;

BOOL result = FALSE;
if (cb == 0) return result;

fASCII = TRUE;
curr = 0;
while (curr < cb)
{
nb = 0;
b = pbBuff[curr];
if ((b & 0x80) != 0)
{
 fASCII = FALSE;
 if ((b & 0xc0) == 0x80) return result;
 else if ((b & 0xe0) == 0xc0) nb = 1;
 else if ((b & 0xf0) == 0xe0) nb = 2;
 else if ((b & 0xf8) == 0xf0) nb = 3;
 else if ((b & 0xfc) == 0xf8) nb = 4;
 else if ((b & 0xfe) == 0xfc) nb = 5;
 else return result;

 if (curr + nb >= cb) return result;

 for (i = 1; i <= nb; i++)
 {
  if ((pbBuff[i + curr] & 0xC0) != 0x80) return result;
 }
}
curr += nb + 1;
}
result = !fASCII;
return result;
}


 
clickmaker ©   (2009-12-14 15:20) [12]

лень писать $80 вместо StrToInt64("0x80") ?


 
Евгений471   (2009-12-14 17:24) [13]


> лень писать $80 вместо StrToInt64("0x80") ?

яж указал, как есть в исходном - так и написал, кого не устроит вариант - поправить недолго.



Страницы: 1 вся ветка

Текущий архив: 2010.02.14;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.01 c
15-1260309385
GanibalLector
2009-12-09 00:56
2010.02.14
PortMon


2-1260808991
alexan
2009-12-14 19:43
2010.02.14
Вопрос по Delphi


15-1260142278
KilkennyCat
2009-12-07 02:31
2010.02.14
Стены и мармелад


1-1237819822
Marfusha
2009-03-23 17:50
2010.02.14
Запуск макроса OpenOffice из Delphi


15-1260394794
kyn66
2009-12-10 00:39
2010.02.14
Avast тормозит загрузку таблиц