DLL для определения кодировки?
Select messages from
# through # FAQ
[/[Print]\]

Total Commander -> Написание плагинов для Total Commander

#1: DLL для определения кодировки? Author: Alextp PostPosted: Mon Aug 16, 2010 23:32
    —
Ищется код(лучше- DLL!) для определния кодировки файла, если нету BOM. По первым NN Кб. Для плагина Syn2.

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

#2:  Author: Alextp PostPosted: Tue Aug 17, 2010 00:29
    —
Посмотрел код akelpad- непонятно, какие-то watermarks-массивы, что они значат не понял (а тупо переводить код не хочется)

#3:  Author: Loopback PostPosted: Tue Aug 17, 2010 09:45
    —
Насколько я понимаю, нужно определить UTF-8 или нет, т.к. BOM к другого рода кодировкам (типа 1251, KOI-8 ) не имеет отношения. Я пользуюсь такой функцией (где-то когда-то нашел):

Code:

function IsUTF8Memory(AMem: PBYTE; ASize: Int64): boolean;
var
  i: Int64;
  c: Integer;

  function UTF8CharLength(const c: BYTE): Integer;
  begin
    // First Byte: 0xxxxxxx
    if ((c and $80) = $00) then
      Result:=1
    // First Byte: 110yyyyy
    else if ((c and $E0) = $C0) then
      Result:=2
    // First Byte: 1110zzzz
    else if ((c and $F0) = $E0) then
      Result:=3
    // First Byte: 11110uuu
    else if ((c and $F8) = $F0) then
      Result:=4
    // not valid, return the error value
    else
      Result:=-1;
  end;

  //After than you check all the trail bytes for that characters (if any)
  //for conformity with this:
  function UTF8IsTrailChar(const c: BYTE): BOOLEAN;
  begin
    // trail bytes have this form: 10xxxxxx
    Result:=((c and $C0) = $80);
  end;

begin
  Result := True;
  i := 0;
  while (i < ASize) do
  begin
    // get the length if the current UTF-8 character
    c:=UTF8CharLength(AMem^);
    // check if it is valid and fits into ASize
    if ((c>= 1) and (c <= 4) and ((i+c-1) < ASize)) then
    begin
      inc(i, c);
      inc(AMem);
      // if it is a multi-byte character, check the trail bytes
      while (c>1) do
      begin
        if (not UTF8IsTrailChar(AMem^)) then
        begin
          Result := False;
          break;
        end
        else
        begin
          dec(c);
          inc(AMem);
        end;
      end;
    end
    else
    begin
      Result:=False;
    end;
    if (not Result) then break;
  end;
end;

#4:  Author: Alextp PostPosted: Tue Aug 17, 2010 10:20
    —
Не только UTF8: ANSI, OEM, KOI8, UTF8. Спасибо за ф-цию. осталось ANSI/OEM/KOI8

#5:  Author: Loopback PostPosted: Tue Aug 17, 2010 10:35
    —
Определение этих кодировок - уже по-любому статистические алгоритмы. Их вроде найти не проблема. Например, вот. Сначала определяем, UTF-8 ли текст, и если нет - смотрим кодировку.

#6:  Author: Alextp PostPosted: Tue Aug 17, 2010 11:50
    —
тестирую код №2. Файл- atorg.net.ru/temp/beta/cp.rar
Показывает "Ansi" для OEM строки -плохо

#7:  Author: MVVLocation: Ростов-Дон PostPosted: Tue Aug 17, 2010 12:53
    —
Определение этих кодировок уже зависит от кодовой страницы. Для русской будет один результат, для каких-нибудь еще - другой. Наверное можно попробовать составить список букв, действительных для каждой кодировки, и подсчитывать число букв текста, совпадающих с ними - где будет больше, та кодировка скорее используется. Но опять же, до какой-то степени множества символов кодировок пересекаются - на поле в 128 символов особо не разгуляешься.

#8:  Author: Alextp PostPosted: Sat Jan 21, 2012 21:30
    —
(Up)
Кто-нибудь может за небольшую плату сделать dll, для определения "'это - UTF8 без BOM", с настройкой "для русского/ немецкого/ ..... "? могу дать пример на C. из сорса Notepad++.

Добавлено спустя 40 секунд:

точнее Akelpad

#9:  Author: ApceHLocation: Димитровград PostPosted: Sat Jan 21, 2012 23:19
    —
Alextp
Вот мой код чуть более общий:
Code:
type
  TEncodingType = (ANSI, UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE);

function DetectEncodingType(hOpenedFile: Cardinal): TEncodingType;
//вялое определние кодировки
//файл должен быть уже открыт на чтение
var
  buf: array[0..3] of AnsiChar;
begin
  Result := ANSI;
  FileRead(hOpenedFile, buf, 4);
  case buf[0] of
    #$EF:
      begin
        if (buf[1] = #$BB) and (buf[2] = #$BF) then
        begin
          FileSeek(hOpenedFile, 3, spBegin);
          Result := UTF8;
        end;
      end;
    #$FE:
      begin
        if (buf[1] = #$FF) then
          FileSeek(hOpenedFile, 2, spBegin);
        Result := UTF16BE;
      end;
    #$FF:
      begin
        if (buf[1] = #$FE) then
          if (buf[2] = #$00) and (buf[3] = #$00) then
          begin
            FileSeek(hOpenedFile, 4, spBegin);
            Result := UTF32LE;
          end
          else
          begin
            FileSeek(hOpenedFile, 2, spBegin);
            Result := UTF16LE;
          end;
      end;
    #$00:
      begin
        if (buf[1] = #$00) and (buf[2] = #$FE) and (buf[3] = #$FF) then
        begin
          FileSeek(hOpenedFile, 4, spBegin);
          Result := UTF32BE;
        end;
      end;
  else
    FileSeek(hOpenedFile, 0, spBegin);
  end;
end;

А среди 8-битных делал только на C#. Определяло практически всё правильно. Если надо скину.

#10:  Author: Alextp PostPosted: Sat Jan 21, 2012 23:23
    —
Мне же детектить текст UTF8 без BOM. А у вас по сигнатуре. Не то. А на С# оно детектит UTF8?

#11:  Author: CaptainFlintLocation: Москва PostPosted: Sun Jan 22, 2012 14:33
    —
Alextp
В общем случае задача неразрешима, потому что если текст целиком на английском, то в ANSI и UTF-8 он будет выглядеть идентично. Да и сам по себе UTF-8 принципиально от ANSI не отличается. Так что как минимум возникает вопрос о приоритетах списка кодировок.

Тому, кто захочет этим заниматься, могу подкинуть лишь идею для реализации, основанную на поведении Тотала (CompareUtf8Detect): пробежаться по файлу, оценивая его с точки зрения допустимости в UTF-8. Если встретилась хотя бы одна недопустимая последовательность байтов, значит, это ANSI. Если встретилась хотя бы одна допустимая мультибайтовая последовательность — с определённым риском можно считать, что это UTF-8 (хотя реально это может быть и ANSI, гарантий нет). Если нет ни того, ни другого, то выбор между ANSI и UTF-8 придётся делать волевым решением (или опцией). Дополнительно (опять-таки, по мотивам Тотала) можно для HTML/XML/CSS-файлов поискать сигнатуры кодировок и встроить их в описанный алгоритм предпочтений.

Следующий уровень для наворотов — учёт языковых особенностей (что если файл русскоязычный, то большинство символов там будет не просто UTF-8, а из конкретного диапазона), но это очень опасный шаг, если методика планируется для повсеместного применения: каждый язык придётся изучать на предмет алфавита и используемых символов, для каждого хардкодить списки последовательностей… Плюс есть вероятность, что из-за этих наворотов точность определения кодировки для неизвестных языков уменьшится, и придётся либо активно дорабатывать списки символов для большого количества языков (возможно, тем самым ещё сильнее ухудшая работу с оставшимися неподдерживающимися языками), либо предусматривать конфигурируемость алгоритма.

#12:  Author: Alextp PostPosted: Sun Jan 22, 2012 15:55
    —
Нужно не "общий случай", а хотя бы как. Как сделано в Akelpad. хотя бы
А навороты не нужны пока

Добавлено спустя 3 минуты:

PS. спасибо, что расписал.

#13:  Author: Alextp PostPosted: Wed Jan 25, 2012 23:59
    —
http://ghisler.ch/board/viewtopic.php?p=240222#240222

#14:  Author: ChusikLocation: Волгоград PostPosted: Fri Jan 27, 2012 17:50
    —
Вот неплохая библиотека (исходники на delphi), может быть использована как напрямую из кода, так и в виде dll.



Total Commander -> Написание плагинов для Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Page 1 of 1

Powered by phpBB © 2001, 2005 phpBB Group