Текущий архив: 2003.02.17;
Скачать: CL | DM;
ВнизKoi8??? Найти похожие ветки
← →
!...Stel (2002-12-31 08:51) [0]Уважаемые, который день ломаю голову и не как не могу определить кодиравку Koi8. И что характерно, нет никаких соображений. Никто не знает, как это делается?
← →
Gandalf (2002-12-31 10:23) [1]Как и все остальные, проверяешь часто вхождения символов из русского алфавита в предположении, что это "та" кодировка - эсли таких довольно много - значит это она и есть.
← →
!...Stel (2002-12-31 14:52) [2]Проверкой символов здесь не получится, потому, что Koi похожа на ANSI1251. Вот пример такой проверки символов:
const
WinSymbols:PChar=#242#243#0;
KoiSymbols:PChar=#225#224#0;
var i,w,k,Handle:integer;
st,p:PChar;
begin
for i:=0 to SendMessage(Form1.RichEdit1.Handle,WM_GETTEXT, $FFD, longint(@st[0]))-1 do
begin
P:=WinSymbols;
while p[0]<>#0 do
begin
if p[0]=st[i] then
begin
inc(w);
end;
inc(p);
end;
P:=KoiSymbols;
while p[0]<>#0 do
begin
if p[0]=st[i] then
begin
inc(k);
end;
inc(p);
end;
if w>k then win:=true else koi:=true;
end;
Но врезультате получается, что w=k. Мож чё ещё посоветуете.
← →
ggrisha (2002-12-31 15:18) [3]например получаешь 10 наиболее часто встречающихся кодов в тексте. Для русского текста это будут буквы е, а, о, и т.д. и потом сравниваешь эти коды с кодами соответствующих букв в каждой из кодировок. Выделяешь кодировку с наибольшем количеством совпадений.
← →
Gandalf (2002-12-31 16:43) [4]Да тут методики, которые не могут дать 100% результат, чемто сродни задаче ИИ и здавого смысла. Например частота встречи букв. Потом более 3 гласных подряд или 4 согласных в русском языке не бывает (искл. абревиатуры). Можно игнорировать слова начинающиеся с ы,ь,ъ - если такие есть кодировка не та. Или повторы ыы, ьь, ъъ, и т.п. Можно проверять на глупый регистр, ПрАвДа НеКоТоРЫЕ ЛюБяТ ХАКЕрский СтИлЬ. И другие не строгие правила. дальше идет только подключение словоря :)
← →
!...Stel (2003-01-01 09:59) [5]Но я чувствую это будет так долго определяться, например если файлик размером так 1-2мб. А ещё потом перекодировать надо будет...
← →
Anatoly Podgoretsky (2003-01-01 10:56) [6]Ну ты наверно в курсе, что файл можно не обрабатывать полностью
← →
don-do (2003-01-03 11:23) [7]Можно воспользоваться тем что в cp1251 первыми идут заглавные буквы а в KOI8-r прописные, по правилам русского языка слова состоят или из одинаковых букв или начинаются с заглавной, хотя написать можно по всякому.
← →
bolega (2003-01-05 13:44) [8]Вот кусок из моей рабочей проги.
Автора алгоритма не знаю.
Часть 1.
const
DOS_2_Win: array[$80..$FF] of byte=(
$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF,
$D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF,
$E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7,$E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF,
$B0,$B1,$B2,$A6,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC,$BD,$BE,$AC,
$C0,$C1,$C2,$C3,$C4,$86,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF,
$D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7,$87,$D9,$DA,$DB,$DC,$DD,$DE,$DF,
$F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF,
$A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2,$B0,$F9,$B7,$FB,$B9,$A4,$FE,$A0);
KOI_2_DOS: array[$80..$FF] of Byte = (
$C4,$C3,$Da,$BF,$C0,$D9,$C3,$B4,$C2,$C1,$C5,$DF,$DC,$DB,$DD,$DE,
$B0,$B1,$b2,$f4,$fe,$f9,$fb,$f7,$f3,$f2,$ff,$f5,$f8,$fd,$fa,$f6,
$cd,$ba,$d5,$f1,$d6,$c9,$b8,$b7,$bb,$d4,$d3,$c8,$be,$bd,$bc,$c6,
$c7,$cc,$b5,$f0,$b6,$b9,$d1,$d2,$cb,$cf,$d0,$ca,$d8,$d7,$ce,$fc,
$ee,$a0,$a1,$e6,$a4,$a5,$e4,$a3,$e5,$a8,$a9,$aa,$ab,$ac,$ad,$ae,
$af,$ef,$e0,$e1,$e2,$e3,$a6,$a2,$ec,$eb,$a7,$e8,$ed,$e9,$e7,$ea,
$9e,$80,$81,$96,$84,$85,$94,$83,$95,$88,$89,$8a,$8b,$8c,$8d,$8e,
$8f,$9f,$90,$91,$92,$93,$86,$82,$9c,$9b,$87,$98,$9d,$99,$97,$9a);
var
KOI_2_WIN:array[$80..$FF] of byte;
procedure MakeKOITable;
var i:integer;
begin
for i:=$80 to $FF do KOI_2_WIN[i]:=DOS_2_Win[KOI_2_DOS[i]];
end;
procedure DOSToWin(var s:string);
var k,i:integer;
begin
k:=Length(s);
for i:= 1 to k do
if byte(s[i])>$7F then
s[i]:=char(DOS_2_Win[byte(s[i])]);
end;
procedure KOIToWin(var s:string);
var k,i:integer;
begin
k:=Length(s);
for i:= 1 to k do
if byte(s[i])>$7F then
s[i]:=char(KOI_2_Win[byte(s[i])]);
end;
procedure DecodeHTM(const fname:string);
// автоматич. распознавание кодировки и перекодирование в Win1251
type
TCodePage=(cpWin1251,cp866,cpKOI8R);
PMap=^TMap;
TMap=array[#$80..#$FF]of char;
function GetMap(CP:TCodePage):PMap;
{ должна возвращать указатель на таблицу перекодировки из CP в Windows1251
(nil для CP = cpWin1251) }
begin
case CP of
cpWin1251: Result:=nil;
cp866: Result:=@DOS_2_Win;
cpKOI8R: Result:=@KOI_2_WIN;
end
end;
function DetermineRussian(Buf:PChar; Count:Integer):TCodePage;
const
ModelBigrams: array [0..33, 0..33] of Byte = (
{АБВГДЕЖЗИЙКЛМHОПРСТУФХЦЧШЩЪЫЬЭЮЯ_Ё}
← →
bolega (2003-01-05 13:47) [9]продолжение
{А}(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,55,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 }
← →
bolega (2003-01-05 13:48) [10]продолжение 2
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;
const
MaxRusCntLines=10;
MaxLines=200;
var f,fn:TextFile; L:TStringList; RusCnt,Cnt,old,j:integer; p:PChar;
cp:TCodePage; s,newname:string;
begin
AssignFile(f,fname);
L:=TStringList.Create;
RusCnt:=0;
Cnt:=0;
try
Reset(f);
while not EOF(f) do begin
inc(Cnt);
// если в MaxLines не встетилось русских букв - прервем
if Cnt>MaxLines then break;
Readln(f,s);
old:=RusCnt;
// ищем русские символы
for j:=1 to Length(s) do
if byte(s[j]) in [$80..$FF] then begin
inc(RusCnt);
break
end;
if old<>RusCnt then L.Add(s);
// для анализа достаточно MaxRusCntLines строк с русскими буквами
if RusCnt=MaxRusCntLines then break
end;
CloseFile(f);
if L.Count=0 then exit; // нет строк с русскими буквами
p:=PChar(L.Text);
// определим кодировку
cp:=DetermineRussian(p,StrLen(p));
if cp=cpWin1251 then exit;
// копируем файл с одновременным перекодированием
newname:=AppDir+"temp\~2.html";
AssignFile(fn,newname);
Reset(f);
Rewrite(fn);
while not EOF(f) do begin
Readln(f,s);
if cp=cp866 then DOSToWin(s) else KOIToWin(s); // cpKOI8R
Writeln(fn,s)
end;
CloseFile(f);
CloseFile(fn);
// запишем на старое место
FileUtil.CopyFile(newname,fname,nil);
finally
L.Free;
end;
end;
Страницы: 1 вся ветка
Текущий архив: 2003.02.17;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.017 c