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

Вниз

Как определить кодировку?   Найти похожие ветки 

 
vigo   (2005-08-01 14:38) [0]

Добрый день!
Недавно задавал вопрос по перекодировке из DOS в WIN (как выяснилось есть функция OemToChar). Подскажите как написать условие, что функция OemToChar(...) испольнеется если кодировка прочитанной из файла строки (readln(f, s)) DOS"овская.


 
GLFox ©   (2005-08-01 14:44) [1]

Существуют в сободном для изучения доступе алгоритмы автоматического определения кодировки текста.


 
vigo   (2005-08-01 14:53) [2]

в смысле
> автоматического определения кодировки текста.
?


 
vigo   (2005-08-01 15:15) [3]

можно по-подробнее...


 
GLFox ©   (2005-08-01 15:23) [4]

Я так понимаю, ты хочешь определить в какой кодировке у тебя задан входной текст. Если я че не так понял, то просто попрошу - вырази свои мысли яснее.


 
Johnmen ©   (2005-08-01 15:24) [5]

Не существует алгоритма 100%-ого распознавания кодировки.


 
GLFox ©   (2005-08-01 15:29) [6]

>Johnmen ©   (01.08.05 15:24) [5]
Трудно не согласиться...


 
vigo   (2005-08-01 15:54) [7]

Столкнулся с такой проблемой, код:
Readln(F, str);
OemToChar(PChar(str), PChar(str));
...

После этого работаю с строкой и затем пишу в другой файл.
Если кодировка DOS, то никаких проблем. А вот если WIN, то в  файл пишется всякая ... То есть OemToChar нужен если строка в файле DOS"овская. Вот и хотелось бы написать какое-нить условие, что-то вроде:
Readln(F, str);
   if PChar(str) = (DOS"овский)
    then OemToChar(PChar(f_str), PChar(f_str));

То есть если строка не DOS"овская функция не исполняется...


 
vigo   (2005-08-01 15:56) [8]

Опечатка в [7] f_str = str


 
GLFox ©   (2005-08-01 16:00) [9]

Вот лови. Это не мое, а где выковырял не помню...
Метод таблицы модельных распределений:

type
 TCodePage = (cpWin1251, cp866, cpKOI8R);
 PMap = ^TMap;
 TMap = array [ #$80..#$FF] of Char;

function GetMap(CP: TCodePage): PMap;
{ должна возвращать указатель на таблицу перекодировки из CP в Windows1251
 (nil для CP = cpWin1251) }
begin
 GetMap:=nil;
end;

function DetermineRussian(Buf: PChar; Count: Integer): TCodePage;
const
 ModelBigrams: array [0..33, 0..33] of Byte = (
   {АБВГДЕЖЗИЙКЛМHОПРСТУФХЦЧШЩЪЫЬЭЮЯ_Ё}
{А}(0,20,44,12,22,23,16,60,4,9,63,93,47,110,0,16,35,61,81,1,5,13,24,17,12,4,0,0,0,0,14,31,205,1),
{Б}(19,0,0,0,4,19,0,0,8,0,2,15,1,4,41,0,15,5,0,15,0,2,1,0,0,6,16,37,0,0,0,4,3,0),
{В}(97,0,1,0,2,57,0,5,40,0,4,25,2,23,78,2,8,28,4,12,0,1,0,0,8,1,0,40,1,0,0,5,106,3),
{Г}(13,0,0,0,9,5,0,0,15,0,1,17,1,2,96,0,24,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0),
{Д}(63,0,9,1,2,71,1,0,35,0,3,16,2,22,50,2,19,9,2,25,0,2,1,0,1,0,1,9,4,0,1,5,17,4),
{Е}(4,14,15,34,56,22,13,14,2,34,39,77,73,150,6,9,101,64,81,1,0,15,5,12,10,6,0,0,0,0,3,4,235,1),
{Ж}(13,0,0,0,12,47,0,0,16,0,1,0,0,23,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2,2),
{З}(76,2,11,3,11,4,1,0,7,0,2,4,11,24,17,0,6,1,0,8,0,0,0,0,0,0,0,16,6,0,1,4,17,0),
{И}(7,9,32,5,18,60,4,42,31,27,28,46,55,49,12,7,26,60,53,0,5,25,14,28,4,1,0,0,0,0,9,56,255,0),
{Й}(0,0,0,0,2,0,0,0,0,0,1,3,0,3,0,0,0,10,3,0,0,0,0,1,1,0,0,0,0,0,0,0,122,0),
{К}(92,0,3,0,0,7,2,1,39,0,0,27,0,14,110,0,18,5,35,18,0,0,11,0,0,0,0,0,0,0,0,0,5,5,0),
{Л}(85,1,0,2,1,70,6,0,85,0,5,3,0,9,67,1,0,9,0,15,0,0,0,2,0,0,0,9,66,0,15,43,57,4),
{М}(44,0,0,0,0,65,0,0,47,0,1,1,10,15,57,7,0,2,0,24,0,0,0,0,0,0,0,28,0,0,0,8,109,3),
{Н}(139,0,0,1,11,108,0,4,152,0,7,0,1,69,161,0,0,8,25,24,5,1,5,2,0,1,0,83,10,0,1,29,38,5),
{О}(0,72,139,76,74,32,32,19,12,52,21,93,68,72,7,34,93,102,98,1,2,6,6,19,15,2,0,0,0,1,4,9,252,2),
{П}(17,0,0,0,0,43,0,0,14,0,1,9,0,1,125,3,120,1,2,8,0,0,0,0,0,0,0,3,6,0,0,3,2,2),
{Р}(151,1,6,4,3,103,7,0,76,0,4,0,11,10,117,1,0,5,9,39,2,5,0,1,3,0,0,24,7,0,1,10,22,5),
{С}(24,1,21,0,3,39,0,0,33,0,56,41,11,15,58,30,5,30,183,16,0,4,1,4,1,0,0,8,25,0,1,50,41,2),
{Т}(83,0,43,0,3,87,0,0,71,0,9,3,2,26,180,0,55,33,1,23,1,0,1,4,0,0,0,20,78,0,0,5,82,4),
{У}(3,6,7,14,19,8,13,6,0,1,13,15,10,7,0,12,17,16,19,0,1,3,0,12,5,8,0,0,0,0,22,1,65,0),
{Ф}(4,0,0,0,0,4,0,0,11,0,0,1,0,0,9,0,3,0,0,4,1,0,0,0,0,0,0,0,0,0,0,0,2,0),
{Х}(9,0,2,0,0,2,0,0,5,0,0,1,0,5,26,0,4,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,76,0),
{Ц}(5,0,0,0,0,16,0,0,48,0,1,0,0,0,4,0,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,3,0),
{Ч}(30,0,0,0,0,52,0,0,23,0,3,1,0,14,1,0,0,0,36,5,0,0,0,0,1,0,0,0,1,0,0,0,2,2),
{Ш}(13,0,0,0,0,28,0,0,17,0,4,4,0,4,3,0,0,0,1,3,0,0,0,0,0,0,0,0,3,0,0,0,1,1),
{Щ}(6,0,0,0,0,23,0,0,16,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1),
{Ъ}(0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0),
{Ы}(0,5,14,1,3,28,0,2,0,22,6,19,21,2,0,5,4,7,10,0,0,37,0,3,4,0,0,0,0,0,0,1,84,0),
{Ь}(0,1,0,0,0,9,0,10,1,0,13,0,2,26,0,0,0,10,3,0,0,0,1,0,6,0,0,0,0,0,6,4,117,0),
{Э}(0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,31,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),
{Ю}(0,5,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,1,15,0,0,0,1,4,1,15,0,0,0,0,0,0,38,0),
{Я}(0,0,9,2,7,10,3,19,0,0,1,6,7,8,0,0,2,6,19,0,0,3,5,1,0,3,0,0,0,0,5,2,177,0),
{_}(42,80,193,43,109,41,18,53,159,0,144,27,83,176,187,229,70,231,99,47,15,13,6,58,7,0,0,0,0,38,0,22,0,2),
{Ё}(0,0,0,0,3,0,0,0,0,0,2,4,4,8,0,0,5,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
{ "рейтинг" буквы Ё условно принимается равным 1/20 от "рейтинга" буквы E,
  если сочетание с участием Ё корректно, иначе - 0 }
type
 TVariation = array [0..33, 0..33] of Integer;
var
 I, J, iC, iPredC, Max: Integer;
 C: Char;
 CP: TCodePage;
 D, MinD, Factor: Double;
 AMap: PMap;
 PV: ^TVariation;
 Vars: array [TCodePage] of TVariation;
begin
 DetermineRussian:=cpWin1251; { по yмолчанию }
{ вычисление распределений биграмм }
 FillChar(Vars, SizeOf(Vars), 0);
 for CP:=Low(Vars) to High(Vars) do begin
   AMap:=GetMap(CP);
   PV:=@Vars[CP];
   iPredC:=32;
   for I:=0 to Count - 1 do begin
     C:=Buf[I];
     iC:=32;
     if C >= #128 then begin
       if AMap <> nil then C:=AMap^[C];
       if not (C in ["Ё", "ё"]) then begin
         C:=Chr(Ord(C) and not 32); { "a".."я" -> "А".."Я" }
         if C in ["А".."Я"] then iC:=Ord(C) - Ord("А");
       end else iC:=33;
     end;
     Inc(PV^[iPredC, iC]);
     iPredC:=iC;
   end;
 end;
{ вычисление метрики и определение наиболее правдоподобной кодировки }
 MinD:=0;
 for CP:=Low(Vars) to High(Vars) do begin
   PV:=@Vars[CP];
   PV^[32, 32]:=0;
   Max:=1;
   for I:=0 to 33 do
     for J:=0 to 33 do
       if PV^[I, J] > Max then Max:=PV^[I, J];
   Factor:=255 / Max; { ноpмализация }
   D:=0;
   for I:=0 to 33 do
     for J:=0 to 33 do
       D:=D + Abs(PV^[I, J] * Factor - ModelBigrams[I, J]);
   if (MinD = 0) or (D < MinD) then begin
     MinD:=D;
     DetermineRussian:=CP;
   end;
 end;
end;

begin
{ тест: слово "Пример" в разных кодировках (веpоятность ошибок на таких
 коpотких текстах высока - в данном слyчае пpосто повезло!) }
 writeln(DetermineRussian(#$CF#$F0#$E8#$EC#$E5#$F0, 6) = cpWin1251);
 writeln(DetermineRussian(#$8F#$E0#$A8#$AC#$A5#$E0, 6) = cp866);
 writeln(DetermineRussian(#$F0#$D2#$C9#$CD#$C5#$D2, 6) = cpKOI8R);
 readln;
end.


 
vrem   (2005-08-01 16:57) [10]

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


 
vigo   (2005-08-01 16:58) [11]

так и сделал - пока другого выхода не вижу... :(



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

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

Наверх




Память: 0.5 MB
Время: 0.042 c
1-1122890294
Dust
2005-08-01 13:58
2005.08.21
народ, оцените код


3-1121240176
Uran
2005-07-13 11:36
2005.08.21
Как скопировать строку в ADOQuery?


4-1119610541
DelphiN!
2005-06-24 14:55
2005.08.21
Вызов процедуры основного модуля из потока


4-1120221767
Silence
2005-07-01 16:42
2005.08.21
Надо получить позицию символа в мемо при движении мышки...


4-1120035773
DarkSet
2005-06-29 13:02
2005.08.21
открытие файла приложением