Разпознаване кодировката на файл?
Какъв е критерият, по който може да се разпознае кодировката на даден файл?
Има едно понятие byte order mark (BOM) - няколко служебни символа в началото на файловете.
За UTF-8 слагането на такъв префикс (EF BB BF) не е задължително, а понякога дори вреди (тук за пример може да се вземе скриптът на IE за импорт на букмарки, който се сърди, ако му се подаде файл с BOM и не го разпознава като валиден).
Част от редакторите винаги слагат BOM (напр. Notepad за WinXP), при други е опция (PS Pad), трети никога не го добавят.
Въпросът ми е: когато файлът не започва с BOM, как някои програми (Notepad) въпреки това успешно познават дали е UTF-8 или ANSI? Какъв е алгоритъма?
Re: Разпознаване кодировката на файл?
Виж разликата
text - aaaaaa.........
ANSI - 61 61 61 61 61.....
UTF8 - FF FE 61 00 61 00 .....
Re: Разпознаване кодировката на файл?
Това, което си дал е Unicode (UTF-16, little-endian).
Моят въпрос е за:
[EF BB BF] 61 61 61 61 61
// добавено:
Разговарях по въпроса с автора на един добър онлайн дешифратор на текстове с неизвестен енкодинг. При неговата задача обаче предварително е известно на какъв език се очаква да е написан текста и с анализ на думите може да се отгатне и кодировката.
Възможно е Нотпад да чете от настройките на Windows кой е езика и да избира кодировката, в която би имало повече букви от съответната азбука. Чух, че при голям файл, в който кирилицата се среща за първи път чак към края, се случвало и той да греши.
За сега това ми стига :)
Re: Разпознаване кодировката на файл?
Първо: в rfc-3629 се казва, че при наличие на разпознавателен механизъм използването на BOM не е желателно (абе направо си е забранено)
Второ: има прост алгоритъм за автоматично разпознаване на UTF-8 кодиран текст.
Кодирането на кратко е следното: всеки кодиран унокод знак започва с поредицата (1(1..))0yyy..., т.е. n на брой битове единица последвани от нулев бит, като броя на началните ненулеви битове показва колко байта общо са за разкодиране. Ако n е по-голямо от нула следващите байтове задължително трябва да започват с 10...., което пък забранява n=1 за първия байт. Или алгоритъма ще озглежда някак си така:
Код:
function NumStartOnes(c: integer): integer;
begin
Result:=0;
while (n and $80) <> 0 do begin
inc(Result);
n:=n shl 1;
end;
end;
function IsUTF8(S: string): boolean;
var
RemBytes: integer;
n: integer;
i: integer;
begin
Result:=false;
RemBytes:=0;
for i:=1 to Length(S) do begin
n:=NumStartOnes(integer(S[i]));
if RemBytes>0 then begin
if n<>1 then
Exit; //wrong start code for remaining bytes
Dec(RemBytes);
end else begin
if (n=1) or (n>4) then
Exit; //wrong start code for first byte
if n>1 then
RemBytes:=n-1;
else
RemBytes:=0;
end;
end;
Result:=RemBytes=0; //if there are missing bytes
end;