Страница 1 из 1

DLL для определения кодировки?

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

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

Добавлено: Вт авг 17, 2010 00:29
Alextp
Посмотрел код akelpad- непонятно, какие-то watermarks-массивы, что они значат не понял (а тупо переводить код не хочется)

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

Код: Выделить всё

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;

Добавлено: Вт авг 17, 2010 10:20
Alextp
Не только UTF8: ANSI, OEM, KOI8, UTF8. Спасибо за ф-цию. осталось ANSI/OEM/KOI8

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

Добавлено: Вт авг 17, 2010 11:50
Alextp
тестирую код №2. Файл- atorg.net.ru/temp/beta/cp.rar
Показывает "Ansi" для OEM строки -плохо

Добавлено: Вт авг 17, 2010 12:53
MVV
Определение этих кодировок уже зависит от кодовой страницы. Для русской будет один результат, для каких-нибудь еще - другой. Наверное можно попробовать составить список букв, действительных для каждой кодировки, и подсчитывать число букв текста, совпадающих с ними - где будет больше, та кодировка скорее используется. Но опять же, до какой-то степени множества символов кодировок пересекаются - на поле в 128 символов особо не разгуляешься.

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

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

точнее Akelpad

Добавлено: Сб янв 21, 2012 23:19
ApceH
Alextp
Вот мой код чуть более общий:

Код: Выделить всё

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#. Определяло практически всё правильно. Если надо скину.

Добавлено: Сб янв 21, 2012 23:23
Alextp
Мне же детектить текст UTF8 без BOM. А у вас по сигнатуре. Не то. А на С# оно детектит UTF8?

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

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

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

Добавлено: Вс янв 22, 2012 15:58
Alextp
Нужно не "общий случай", а хотя бы как. Как сделано в Akelpad. хотя бы
А навороты не нужны пока

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

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

Добавлено: Ср янв 25, 2012 23:59
Alextp

Добавлено: Пт янв 27, 2012 17:50
Chusik
Вот неплохая библиотека (исходники на delphi), может быть использована как напрямую из кода, так и в виде dll.