уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Материалы предоставлены
автором блога «Переводы от GunSmoker«

Небольшая аннотация к статье.

Думаю, что большинство разработчиков в процессе работы с web-страницами сталкивались с такой проблемой — определение кодировки страницы и перевод всего контента web-страницы в необходимую для дальнейшей работы кодировку.

Обычно вопросы, встречающиеся на форумах, по проблеме кодировок пестрят такими словосочетаниями как «кракозябры вместо русских букв» и т.д. Вариантов решения этой проблемы несколько, в том числе и вариант, предлагаемый Александром безусловно может и должен использоваться при работе с кодировками, а именно — использование в Delphi возможностей, предоставляемых библиотекой mlang.dll.

1. Введение в работу с MLang.

Во-первых, следует упомянуть, что библиотека mlang.dll присутствует во всех версиях windows, включая windows 95 с установленным Internet Explorer. Поэтому, использование этой бибилиотеки в Ваших приложениях не должно привести к каким-либо проблемам, необходимости распространения библиотеки вместе с приложением и т.д.

Судя по описанию на msdn.com основным назначением MLang является:

помощь разработчикам в решении проблем, возникающих в международных масштабах Интернета. Эти инструменты позволяют разработчику иметь дело с целым рядом международных кодировок…

Билиотека MLang, в числе прочих своих возможностей, позволяет нам:

  1. Перечислять кодовые страницы из базы MIME
  2. Преобразовывать кодировку текста
  3. Определять в какой кодировке находится текст
  4. и ещё много-много разных возможностей.

Чтобы воспользоваться воможностями библиотеки Mlang в Delphi нам потребуется заголовочный файл, ссылка на который находится в конце статьи. В этом файле определены необходимые типы данных для работы с библиотекой, перечислены интерфейсы и т.д. Давайте попробуем написать простенький пример, реализующий минимальные возможности библиотеки при работе с кодовыми страницами.

2.  Пример реализации возможностей MLang в Delphi

Для начала, приведем пример перечисления всех кодовых страниц, имеющихся в базе MIME.

Создаем новое приложение и бросаем на главную форму всего один компонент — Memo.

В uses подключаем следующие модули: MLang,  ActiveX,  ComObj.

Теперь, в обрабочике onCreate формы определим следующие переменные:

var MultiLang: IMultiLanguage;
    ECP: IEnumCodePage;
    CPI: tagMIMECPINFO;
    Fetched: Cardinal;

Краткое описание переменных:

  • IMultiLanguage — это интерфейс, который собирает информацию о наборах символов, кодовых страницах или локалях из базы данных MIME и преобразует строки из одной кодировки в другую.
  • IEnumCodePage — интерфейс, с помощью которого можно получить информацию о кодовых страницах или определить, какие кодовые страницы допускаются при работе.
  • tagMIMECPINFO — структура, содержащая детальную информацию о кодовой странице.

Теперь, создаем необходимые объекты:

...
begin
  MultiLang:=CoCMultiLanguage.Create as IMultiLanguage;
  FillChar(CPI, SizeOf(CPI), 0);
  Fetched := 0;
  OleCheck(MultiLang.EnumCodePages(MIMECONTF_BROWSER, ECP));
...

Обратите внимание на то, как создается ECP. Метод EnumCodePages создает объект ECP (IEnumCodePage), используя один из доступных флагов, которые используются для контроля перечисления кодовых страниц. В нашем случае — это флаг MIMECONTF_BROWSER т.е. перечисляем кодовые страницы предназначенные для отображения в браузере клиента. Также, Вы можете использовать ряд других флагов при перечислении доступных кодировок, например, MIMECONTF_MAILNEWS — кодовые страницы предназначенные для отображения в почтовых и новостных клиентах и т.д. Все доступные флаги определены в модуле MLang.pas.
Теперь перечислим все доступные кодировки и занесем их в Memo1:

...
  while Succeeded(ECP.Next(1, CPI, Fetched)) do
    begin
     if Fetched <= 0 then
        Break;
      Memo1.Lines.Add(CPI.wszWebCharset)
    end;
end;

Метод Next у IEnumCodePage возвращает массив структур tagMIMECPINFO для указанного количества кодовых страниц. Параметры метода:

function Next(celt: Cardinal; out rgelt: tagMIMECPINFO; out pceltFetched: Cardinal): HResult; stdcall;
  • celt — определяет количество элементов, которые будут возвращены в rgelt
  • rgelt — указатель на массив, в котором возвращаются структуры tagMIMECPINFO
  • pceltFetched — указатель на целое число, определяет количество структур tagMIMECPINFO фактически вернувшиеся в rgelt. Возвращаемое значение может быть меньше значения, заданного в параметре celt.

Теперь, что касается непосредственно структуры tagMIMECPINFO. Вот её описание в Delphi:

tagMIMECPINFO = packed record
    dwFlags: Cardinal;
    uiCodePage: SYSUINT;
    uiFamilyCodePage: SYSUINT;
    wszDescription: array[0..63] of WideChar;
    wszWebCharset: array[0..49] of WideChar;
    wszHeaderCharset: array[0..49] of WideChar;
    wszBodyCharset: array[0..49] of WideChar;
    wszFixedWidthFont: array[0..31] of WideChar;
    wszProportionalFont: array[0..31] of WideChar;
    bGDICharset: Byte;
  end;

dwFlags — сочетание значений, определенных в MIMECONTF или 0x0000.
uiCodePage — идентификатор кодовой страницы, который подходит к поддержке определения национальных языков (NLS).
uiFamilyCodePage — кодовая страница Microsoft Windows, с которой связан uiCodePage, а также атрибуты wszFixedWidthFont и wszProportionalFont. Если не определена в базе данных, то этот элемент имеет то же значение как и uiCodePage.
wszDescription — описание для uiCodePage.
wszWebCharset — имя набора символов соответствующих uiCodePage в форме, которую можно использовать с браузерами, например windows-1251, utf-8 и т.д.. Если нет в базе данных MIME, этот элемент имеет то же значение как и wszBodyCharset.
wszHeaderCharset — имя набора символов, которое соответствует uiCodePage и которое может быть использовано почтовым агентом в тегах заголовков. Если нет в базе данных, этот элемент имеет то же значение, что и wszBodyCharset.
wszBodyCharset — имя наборов символов, которое может быть использовано в тела почтового сообщения. Если нет в базе данных, этот элемент возвращает NULL.
wszFixedWidthFont — шрифт по умолчанию, который будет использоваться для моноширинного шрифта. Браузер может использовать это имя, чтобы выбрать шрифт для элемента текстового поля.
wszProportionalFont — шрифт, который будет использоваться по умолчанию для пропорциональных шрифтов. Браузер может использовать это имя, чтобы выбрать шрифт для элемента текста.
bGDICharset — Windows представление набора символов, который соответствует uiCodePage.
В приведенном выше листинге мы выводим в Memo список кодировок для браузера, т.е. те значения, которые обычно содержаться в мета-теге web-страницы или передаются в заголовках.
Теперь, можете поэкспериментировать с различными полями структуры, а мы перейдем непосредственно к предложению Александра по работе с кодировками web-станиц.

3. Работа с кодировками Web-страниц. Действие MLang в Delphi.

Александр предоставляет нам с Вами в использование ещё один модуль HtmlCPConvert, который содержит высокоуровневую обёртку над MLang. В модуле определены следующие методы:
CharsetNameToCharset — переводит содержимое мета-тега charset в CPID:Cardinal, годный для передачи в метод MultiByteToWideChar (содержится в kernel32.dll, модуль windows.pas)
RawHTMLToHTML — получает из web-страницы мета-тег с описанием кодировки, вызывает CharsetNameToCharset, после чего конвертирует весь буфер в WideString для получения читабельного текста.
HTMLToRawHTML — функция с действием противоположным RawHTMLToHTML, которая по подготовленному HTML-коду в unicode (WideString) делает HTML в нужной кодировке (кодировка снова берётся из мета-тэга «charset»).
Использование приведенных выше функций имеет ряд очевидных преисуществ перед теми методами, которые рассматривались в том числе и в моем блоге. Обычно мы ограничиваемся фиксированным набором кодировок с которыми собираемся работать в своей программе, например win-1251 и utf-8, не учитывая при этом такие кодировки как KOI-8R, которые также встречаются на web-страницах Интернета. Предлагаемый же способ дает нам возможность использовать в работе сразу всю базу MIME для работы с web-страницами, не ограничиваясь при этом только латиницей или кирилицей — достаточно вывести весь набор кодировок, поддерживаемых браузеров, чтобы прикинуть возможности использования модуля HtmlCPConvert.
Так что, надеюсь, что предоставленная Александром информация найдет широкое применения в Ваших проектах, в т.ч. и при разработке различного рода парсеров.
Ну и, конечно же, сами модули MLang.pas и HtmlCPConvert.pas в одном архиве:

[download id=»41″ format=»1″]
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
25 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Schnaps
Schnaps
02/04/2010 13:34

Попробовал, при преобразовании строки из UTF-8 в win-1251 всесто русских символов получил вопросики. может есть особенности использования? приведите пример пожалуйста

Schnaps
Schnaps
04/04/2010 16:55

в ридере упала рассылка с блога, думаю мой пример уже лишний, почитаю сейчас статью, если не получится напишу уж тогда

Максим
Максим
17/06/2010 22:04

Подскажите пожалуйста, как установить модули MLang и HtmlCPConvert.
Пытаюсь поставить на Делфи 6 — выдает ошибку — не может найти Etypes.dcu.

Или обязательно нужна девятая версия?

Дмитрий
Дмитрий
28/06/2010 06:26

спасибо, статья информативна и помогла мне;)

Орион
15/07/2010 15:15

А как быть если кодировка в заголовке возвращаемого файла отличается от кодировки в мета файла?

Орион
15/07/2010 23:48

Респект. Сейчас попробовал, заработало. А-то до этого на utf-8 появлялись кракозябры…

SeoGHOST
17/03/2011 00:49

Здравствуйте! Не могли бы вы на конкретном примере показать как можно получать, например, TITLE или содержимые meta-keywords страниц в разных кодировках? было бы отлично.

SeoGHOST
17/03/2011 02:23

Возможно вы не правильно меня поняли. Я имею ввиду, что допустим я должен спарсить Title какой то страницы, адрес этой страниц и соответственно кодировка заранее не известны. То есть соль в том, чтобы разобраться как распознавать кодировку на странице и получать все, как есть на самом деле, а не ??? и крякозябры.  
P.S. Просьба не бить, тухлые помидоры не кидать и не направлять в поиск.

Bazar
Bazar
18/03/2011 01:07

RawHTMLToHTML не желает раскодировать сайт

http://oz.by/
хотя он в кодировке KOI8-R.
Может кто подскажет как его зарусить :)

SeoGhost
SeoGhost
18/03/2011 02:10

Bazar, надеюсь Влад скоро расскажет как разобраться со всеми кодировками и сайтами, а не только с вашим (с) )

Bazar
Bazar
18/03/2011 13:36

я уже понял что эта функция только для UTF-8.
спасибо Влад большое за статьи.
я уже не одно использовал из них :)

Vera
Vera
20/03/2011 02:26

HtmlCPConvert выдает
неизвестный итендификатор UTF8ToUnicodeString(ARawHTML)
Может ETypes.dcu нужен?

евгений
евгений
29/05/2011 13:05

У меня Delphi 7 Enterprise Скачал и скопировал файлы HtmlCPConvert.pas MLang.pas в папку Lib. Подключаю их, возникает ошибка не найден ETypes.dcu. Нашел его в инете, кинул также в Lib. mlang перестал ругаться. Зато ругается и очень сильно  HtmlCPConvert, вываливает кучу ошибок: [Error] HtmlCPConvert.pas(159): Undeclared identifier: ‘UTF8ToUnicodeString’ [Error] HtmlCPConvert.pas(186): Undeclared identifier: ‘IS_TEXT_UNICODE_ASCII16’ [Error] HtmlCPConvert.pas(187): Undeclared identifier: ‘IS_TEXT_UNICODE_REVERSE_ASCII16’ [Warning] HtmlCPConvert.pas(187): Combining signed and unsigned types — widened both operands [Error] HtmlCPConvert.pas(188): Undeclared identifier: ‘IS_TEXT_UNICODE_STATISTICS’ [Error] HtmlCPConvert.pas(189): Undeclared identifier: ‘IS_TEXT_UNICODE_REVERSE_STATISTICS’ [Error] HtmlCPConvert.pas(190): Undeclared identifier: ‘IS_TEXT_UNICODE_CONTROLS’ [Error] HtmlCPConvert.pas(191): Undeclared identifier: ‘IS_TEXT_UNICODE_REVERSE_CONTROLS’ [Error] HtmlCPConvert.pas(192): Undeclared identifier: ‘IS_TEXT_UNICODE_SIGNATURE’ [Error] HtmlCPConvert.pas(193): Undeclared identifier: ‘IS_TEXT_UNICODE_REVERSE_SIGNATURE’ [Error] HtmlCPConvert.pas(194): Undeclared… Подробнее »

trackback
Synapse, несколько полезных функций для работы с текстом | Программирование на Delphi для интернет
30/06/2011 13:33

[…] с библиотекой MLang, о которой писал Vlad в своем блоге. По описанию выглядит привлекательно, единственный […]

Lion
Lion
05/11/2011 15:36

А как быть с такой строкой — %D0%A4%D1%91%D0%B4%D0%BE%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_(%D0%92%D0%BE%D0%BB%D1%8B%D0%BD%D1%81%D0%BA%D0%B0%D1%8F_%D0%BE%D0%B1%D0%BB%D0%B0%D1%81%D1%82%D1%8C)