Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 24 февраля 2010 в 18:59.
Категории: Delphi в Web.


Материалы предоставлены
автором блога "Переводы от 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 - cочетание значений, определенных в MIMECONTF или 0x0000.
uiCodePage - идентификатор кодовой страницы, который подходит к поддержке определения национальных языков (NLS).
uiFamilyCodePage - кодовая страница Microsoft Windows, с которой cвязан 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 в одном архиве:
zip Модули MLang и HtmlCPConvert(6.58 KB)

Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (25)

WP_Cloudy
  • Schnaps пишет:

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

  • Vlad пишет:

    Думал ошибка есть какая-нибудь в HtmlCPConvert. Нету. Все конвертится прекрасно. Дайте пожалуйста адрес странички, которую пробовали конвертировать и листинг кода как Вы конвертировали. А я пока примерчик набросаю в виде поста отдельного — думаю, что многим пригодится

  • Schnaps пишет:

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

  • Vlad пишет:

    ок. Но то, что у вас вопросы появились вместо русских букв — это странно. По идее должны были быть кракозябры всякие, но никак не ???

  • Максим пишет:

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

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

  • Vlad пишет:

    Etypes.dcu можно спокойно удалить из uses — это вспомогательный модуль, который использовал автор модуля в своем проекте.

  • Дмитрий пишет:

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

  • Орион пишет:

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

  • Vlad пишет:

    У MLang есть автоопределение кодировки. Только в этом случае Вам надо немного на MSDN почитать про ту возможность.

  • Орион пишет:

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

  • Vlad пишет:

    Всегда рад помочь :)

  • SeoGHOST пишет:

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

  • Vlad пишет:

    http://www.webdelphi.ru/2011/03/chastichnoe-skachivanie-web-stranichki-s-pomoshhyu-synapse/
    Конкретный пример вытаскивания title из кода странички

  • SeoGHOST пишет:

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

  • Vlad пишет:

    >>P.S. Просьба не бить, тухлые помидоры не кидать и не направлять в поиск.
    да как бы я редко кого пинаю в принципе :) Ок. Теперь более-менее понятно, что имелось в виду. Попробую помочь в следующем посте :)

  • Bazar пишет:

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

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

  • SeoGhost пишет:

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

  • Bazar пишет:

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

  • Vlad пишет:

    Да не за что :)

  • Vera пишет:

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

  • Vlad пишет:

    ETypes.dcu можно смело вычеркивать из uses — этот модуль ни относился к работе с кодировками и содержал вспомогательные функции. ARAwHTML что содержит?

  • евгений пишет:

    У меня 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 identifier: ‘IS_TEXT_UNICODE_ILLEGAL_CHARS’
    [Error] HtmlCPConvert.pas(195): Undeclared identifier: ‘IS_TEXT_UNICODE_ODD_LENGTH’
    [Error] HtmlCPConvert.pas(196): Undeclared identifier: ‘IS_TEXT_UNICODE_NULL_BYTES’
    [Error] HtmlCPConvert.pas(199): Undeclared identifier: ‘IS_TEXT_UNICODE_UNICODE_MASK’
    [Error] HtmlCPConvert.pas(205): Undeclared identifier: ‘IS_TEXT_UNICODE_REVERSE_MASK’
    [Fatal Error] Unit1.pas(7): Could not compile used unit ‘HtmlCPConvert.pas’

  • Vlad пишет:

    HtmlCPConvert — это модуль-обёртка над MLang.pas. Писался модуль под версию D2009-2010, работает и в XE. Ваша версия Delphi в принципе не знает, что такое Unicode, RawByteString и т.д. Константы IS_TEXT_UNICODE_… — лежат в модуле Windows.pas.
    Так что ваш вариант использования MLang — либо писать свою обёртку под D7, либо разбираться с тем как работает MLang и работать без всяких обёрток — ничего сложного в этом нет.

  • Synapse, несколько полезных функций для работы с текстом | Программирование на Delphi для интернет пишет:

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

  • Lion пишет:

    А как быть с такой строкой — %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)

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник

   


первые часы жизни ребенка видео