Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Определение кодировки читаемого файла

590
21 февраля 2007 года
Gigahard
223 / / 03.04.2006
Делаю программу, которая могла бы читать как обычные Ascii файлы, так и файлы в UTF-8.
Вся проблема в том, что в зависимости от кодировки файла, к нему применяется или не применяется функция Utf8ToAnsi().
Соответственно нужно определить, когда эту функцию применять, а когда нет. Т.е. нужно что то вроде функции определения кодировки.
Есть ли такое в природе и если нет, то можно ли как сделать самому?

Первая идея была определять UTF-8 файл по наличию BOM, но есть UTF-8 файлы не содержащие BOM меток... Соответственно этот метод не подходит...
361
21 февраля 2007 года
Odissey_
661 / / 19.09.2006
Считывайте все как UTF-8. У него полная обратная совместимость.
590
21 февраля 2007 года
Gigahard
223 / / 03.04.2006
Да вот не получается... Обратной то совместимости...
Utf8ToAnsi("Ascii строка") возвращает нулевой результат.
1
21 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: Odissey_
Считывайте все как UTF-8. У него полная обратная совместимость.


С каких это пор? Хм. :)

10
21 февраля 2007 года
Freeman
3.2K / / 06.03.2004
Цитата: Gigahard
Т.е. нужно что то вроде функции определения кодировки.
Есть ли такое в природе и если нет, то можно ли как сделать самому?


Код:
function IsTextUTF8(const Source: AnsiString): Boolean;
var
  Chr: Byte;
  I, Octets: Integer;
  AllAscii: Boolean;
begin
  if Source <> '' then
  begin
    Octets := 0;
    AllAscii := True;
    for I := 1 to Length(Source) do
    begin
      Chr := Byte(Source);
      if Chr and $80 <> 0 then
        AllAscii := False;
      if Octets = 0 then
      begin
        if Chr >= $80 then
        begin
          repeat
            Chr := Chr shl 1;
            Inc(Octets);
          until Chr and $80 = 0;
          Dec(Octets);
          if Octets = 0 then
          begin
            Result := False;
            Exit;
          end;
        end;
      end
      else
      begin
        if Chr and $C0 <> $80 then
        begin
          Result := False;
          Exit;
        end;
        Dec(Octets);
      end;
    end;
    Result := (Octets <= 0) and not AllAscii;
  end
  else
    Result := False;
end;


Возможно, стоит занести в FAQ.
590
23 февраля 2007 года
Gigahard
223 / / 03.04.2006
Спасибо за функцию :)
Подходя к вопросу с другой стороны... Вся эта затея с преобразованием utf8 в ascii в принципе нужна для корректного вывода на стандартные контролы... А они вроде как не понимают utf-8... Или все же понимают?
590
01 марта 2007 года
Gigahard
223 / / 03.04.2006
Я в Паскале не силен, но следуя логике приведенного листинга, попытался все это перевести в Сишный код. Вот что получилось:

Код:
bool IsTextUTF8(AnsiString Source)
{
    BYTE Chr;
    int i, Octets;
    bool AllAscii;
    if (Source !="")
    {
        Octets= 0;
        AllAscii= true;
        for (i= 1; Source.Length(); i++)
        {
            Chr = Byte(Source);
            if ((Chr & 0x80) != 0)
                AllAscii = false;
            if (Octets == 0)
            {
                if (Chr >= 0x80)
                {
                    do
                    {
                        Chr= Chr << 1;
                        Octets++;
                    }
                    while((Chr & 0x80) == 0);
                    Octets--;
                    if (Octets == 0)
                        return false;
                }
            }
            else
            {
                if((Chr & 0xC0) != 0x80)
                {
                    return false;
                }
                Octets--;
            }
        }
        return bool ((Octets <= 0) && !AllAscii);
    }
    return false;
}


Единственная проблема, код не работает :(
И что то не могу я въехать в функционал кода... Как оно работает то?
1.9K
01 марта 2007 года
SABROG
242 / / 26.01.2006
Английский текст в UTF8 выглядит точно также как и cp866 и cp1251 и koi8-r. Есть определенная таблица частот встречаемости русских символов в предложениях, таким образом, чем больше текста, тем больше точность определения кодировки. Содержимое файла перекодируется во все доступные кодировки и сравнивается частота встречаемости букв, там где она выше, та кодировка и стоит. Соответственно для других языков нужные свои таблицы.
10
01 марта 2007 года
Freeman
3.2K / / 06.03.2004
Цитата: Gigahard
И что то не могу я въехать в функционал кода... Как оно работает то?


UTF-8 отличается от приведённых SABROG-ом кодировок регулярностью встречающихся октетов, определяемой однозначно, что и делает функция.

Простой поиск в Google по имени функции вывел на китайцев. Обращаем внимание на комментарии в заголовке исходника - это микрочленовский Блокнот. Как функция заработает, Gigahard-у предложение открыть собственную компанию и назвать GigaSoft.

590
01 марта 2007 года
Gigahard
223 / / 03.04.2006
Как говориться, "Нормальные герои, всегда идут в обход..." :D
В общем проверку на UTF-8 сделал так:
Код:
AnsiString output;
if((strlen(tst)>0) && Utf8ToAnsi(tst)!="")
{
        output= Utf8ToAnsi(tst);
        Form1->Caption="UTF-8 Input";
}
else
{
        output= tst;
        Form1->Caption="ASCII Input";
}

tst здесь строка с исходным текстом.
518
06 марта 2007 года
Andreika
101 / / 14.02.2003
Цитата: Gigahard
Как говориться, "Нормальные герои, всегда идут в обход..." :D



Все гениальное просто гы...

Однако стоило бы заморочиться с определением всех возможных кодировок по частоте букв...

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог