Выберите какие наборы кириллицы поддерживает php

Выберите какие наборы кириллицы поддерживает php

Простая фунция перегона кодировки если на странице установлена иная как не в базе

iconv(«WINDOWS-1251», «UTF-8», $row->STAVKA)

$res = ibase_connect($dbname, $dbuser, $dbpassword) or die (ibase_errmsg());
$sql = «SELECT * FROM lots»;

$sth = ibase_query($res, $sql);
while ($row = ibase_fetch_object($sth)) <
echo $row->ID, iconv(«WINDOWS-1251», «UTF-8», $row->STAVKA), «\n»;
echo «
«;

Строковые функции PHP в кодировке UTF-8

Внезапно перестал работать простой скрипт. Задача скрипта — получение HTML-страницы (из браузерной игры) и выборка данных с помощью регулярных выражений. У меня как у новичка это событие вызвало недоумение и легкую панику: ведь все еще вчера работало! В чем же дело?
Пришлось досконально разбираться в работе некоторых PHP-функций.

Код был достаточно примитивным:

$pattern = "#Написать письмо(.*)Боевой уровень#is"; $url = " "; $html = file_get_contents($url); preg_match($pattern, $html, $matches); if (isset($matches[1])) echo $matches[1]; else echo "не найдено";

Получение данных и разбор с помощью простого регулярного выражения.
Надо сказать, что этот код — результат легкой модификации. В исходном варианте регулярка искала по HTML-тэгам. Но вот мне понадобилось найти кусочек между двумя словосочетаниями на русском языке. Я добавила в шаблон поиска русские слова, и именно это изменение стало критичным.

А теперь по порядку.
Сайт игры www.heroeswm.ru выдает страницы в кодировке win-1251. У меня на сервере кодировка UTF-8, поэтому все скрипты — в UTF-8 без BOM.
Исходный скрипт с поиском по HTML-тэгам работал корректно, несмотря на различие кодировок, но когда в шаблон поиска я добавила символы кириллицы, искать и находить перестал. В моей задаче бы очень просто отмахнуться от проблемы и подобрать другой шаблон — без русских слов, но в большинстве случаев это невозможно. Поэтому я решила разобраться досконально: в чем принципиальная разница кодировок, почему она вызывает некорректную работу регулярных выражений, а заодно — какие функции страдают из-за различия кодировок, и как это обходить.

Читайте также:  Document

Для получения данных я использовала функцию file_get_contents() , которая имеет такой синтаксис:

string file_get_contents( string $filename) , где $filename — имя читаемого файла.
Возвращает строку или bool(false) — в случае неудачи при получении данных.

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

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

Имея такой обширный набор знаков, UTF-8 не только позволит использовать на одном сайте буквы разных алфавитов, но и даст некую гарантию того, что русскоязычный сайт будет корректно отображаться даже там, где о существовании кодировок с поддержкой кириллицы (win-1251, KOI8-R, CP866, ISO 8859-5 и др.) даже не подозревают: в Японии, Корее, арабских странах и т.п. Платой за такую универсальность станет несколько больший вес символов при хранении и соответственно большее время их обработки строковыми функциями PHP. Они, кстати, в большинстве случаев будут работать некорректно. Именно с этой проблемой я и столкнулась: регулярка скрипта, записанного в UTF-8, просто не могла правильно найти нужную мне подстроку, включающую знаки кириллицы, на странице, полученной с сайта в Windows-1251.

Логично предположить, что сайтам, на которых будут использовать только кириллицу и латиницу, UTF-8 ни к чему, да и рассматриваемому простому парсеру вполне неплохо «жилось» в win-1251, но бывают ситуации, когда от необходимости подружить эти кодировки и использовать строковые функции PHP просто не отвертеться, например, при разработке проекта в UTF-8.

Чем вызвано некорректное поведение строковых функций?

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

substr('Проверка', 0, 5); // текст в кодировке UTF-8

вернет «Пр�» вместо ожидаемого «Прове»: в UTF-8 символы кириллицы кодируются двумя байтами, вследствие чего мы и видим «кракозябр» — только первый байт символа «о».

Таким образом, в большинстве случаев для работы со строками в UTF-8 потребуется применение специальных функций (например, из расширения PHP mbstring), а иногда и использование обеих (например, для передачи размера строки в байтах в заголовок HTTP нужно будет оставить strlen() , а для подсчета количества символов придется добавить mb_strlen() ).

Синтаксис часто используемых функций, которым может потребоваться замена функциями из расширения PHP mbString:

int strlen( string $string) — возвращает длину строки или 0, если строка пуста.

int strpos( string $haystack , mixed $needle ) — возвращает позицию первого вхождения строки $needle в подстроку $haystack или FALSE, если не найдено.

stripos аналогична предыдущей функции, только поиск регистронезависимый.

string substr( string $string , int $start [, int $length ] ) — позволяет выбрать подстроку, начиная с указанной позиции символа, и при указании третьего параметра — определенной длины.

Для работы в многобайтных кодировках предназначены их аналоги: mb_strlen , mb_strpos , mb_stripos и mb_substr .

Конечно, функций для работы с текстом гораздо больше. Я привела лишь самые популярные.

Особняком стоят функции для работы с регулярными выражениями, предназначенные для поиска подстроки (подстрок), совпадающей с маской, заданной регулярным выражением.

int preg_match( string $pattern , string $subject , array &$matches )

int preg_match_all( string $pattern , string $subject array &$matches ) .

В тексте $subject ищутся совпадения с шаблоном $pattern , заданным регулярным выражением. Результат поиска записывается в переменную $matches . Функция возвращает количество найденных совпадений с шаблоном, в случае ошибки вернет FALSE.

Чтобы в многобайтных кодировках для поиска по шаблону использовать регулярные выражения, в них понадобится добавлять модификатор /u , либо использовать группу функций mb_ereg* .

Пришедшее первым решение — перекодировать в UTF-8 получаемые в win-1251 данные — показалось неудобным. Ведь вслед за перекодировкой все обычные функции придется заменять специальными для работы с UTF-8, или пытаться использовать модификатор /u (забегая вперед, скажу, что он позволяет работать со строками в однобайтных кодировках, «как со строками UTF-8», но не годится для строк в UTF-8). В моем примере лишь одна preg_match() , но на практике так бывает редко.

Поэтому «переворачиваю» задачу: я хочу использовать обычные функции preg_match() , а для этого я буду перекодировать не входящую строку, а шаблон поиска, используя iconv() .

Синтаксис функции:
string iconv($in_charset, $out_charset, $str) — Конвертирует строку $str из кодировки $in_charset в кодировку $out_charset. Возвращает перекодированный текст, не затрагивая исходную переменную.

Функция возвращает строку в новой кодировке, но не изменяет кодировку самой строки. Поэтому

$pattern = "#Написать письмо(.*)Боевой уровень#is"; iconv("UTF-8", "WINDOWS-1251", $pattern); // $pattern остался в исходной кодировке preg_match($pattern, $html, $matches);

работать не будет — $pattern осталась в исходной кодировке UTF-8. Необходимо результат работы iconv присвоить переменной:

$pattern = "#Написать письмо(.*)Боевой уровень#is"; $pattern = iconv("UTF-8", "WINDOWS-1251", $pattern); preg_match($pattern, $html, $matches);

Теперь поиск работает корректно, да только в браузер отдает сплошные кракозябры. Ну, тут уже знаю, что делать: нужно результат перекодировать в рабочую кодировку UTF-8. И тут всплыл второй момент, который для меня не был очевиден, хотя имей я больше опыта, наверняка бы затруднений не вызвал: почему iconv() одни переменные перекодирует, а другие — нет?

 $matches = iconv("WINDOWS-1251", "UTF-8", $matches); ?>

Переменная $matches представляет собой массив, а я попыталась отделаться одной перекодировкой iconv($matches) . Еще раз смотрю описание синтаксиса функций: ну конечно, все параметры должны быть строками, а никак не массивами. То есть необходимо перебрать все значения массива, нуждающиеся в перекодировке, и перевести их в нужную кодировку. В своем примере перебором массива я не занималась, поскольку меня интересовало одно значение, а не весь массив. Его я и указала в качестве параметра функции iconv() .

Вот что у меня получилось в окончательном варианте:

 // устанавливаем кодировку по умолчанию setlocale (LC_ALL, "ru_RU.UTF-8"); header('Content-type: text/html; charset=UTF-8'); $pattern = "#Написать письмо(.*)Боевой уровень#is"; $pattern = iconv("UTF-8", "WINDOWS-1251", $pattern); $url = "http://www.heroeswm.ru/pl_info.php?id=993353"; $html = file_get_contents($url); preg_match($pattern, $html, $matches); if (isset($matches[1])) echo $matches[1] = iconv("WINDOWS-1251", "UTF-8", $matches[1]); else echo "не найдено"; ?>

Источник

Поддерживаемые кодировки символов

В настоящее время модулем mbstring поддерживаются следующие кодировки символов. Любая из этих кодировок символов может быть указаны в параметре encoding функций mbstring.

Следующие кодировки символов поддерживаются в этом расширении PHP:

  • UCS-4*
  • UCS-4BE
  • UCS-4LE*
  • UCS-2
  • UCS-2BE
  • UCS-2LE
  • UTF-32*
  • UTF-32BE*
  • UTF-32LE*
  • UTF-16*
  • UTF-16BE*
  • UTF-16LE*
  • UTF-7
  • UTF7-IMAP
  • UTF-8*
  • ASCII*
  • EUC-JP*
  • SJIS*
  • eucJP-win*
  • SJIS-win*
  • ISO-2022-JP
  • ISO-2022-JP-MS
  • CP932
  • CP51932
  • SJIS-mac** (alias: MacJapanese)
  • SJIS-Mobile#DOCOMO** (alias: SJIS-DOCOMO)
  • SJIS-Mobile#KDDI** (alias: SJIS-KDDI)
  • SJIS-Mobile#SOFTBANK** (alias: SJIS-SOFTBANK)
  • UTF-8-Mobile#DOCOMO** (alias: UTF-8-DOCOMO)
  • UTF-8-Mobile#KDDI-A**
  • UTF-8-Mobile#KDDI-B** (alias: UTF-8-KDDI)
  • UTF-8-Mobile#SOFTBANK** (alias: UTF-8-SOFTBANK)
  • ISO-2022-JP-MOBILE#KDDI** (alias: ISO-2022-JP-KDDI)
  • JIS
  • JIS-ms
  • CP50220
  • CP50220raw
  • CP50221
  • CP50222
  • ISO-8859-1*
  • ISO-8859-2*
  • ISO-8859-3*
  • ISO-8859-4*
  • ISO-8859-5*
  • ISO-8859-6*
  • ISO-8859-7*
  • ISO-8859-8*
  • ISO-8859-9*
  • ISO-8859-10*
  • ISO-8859-13*
  • ISO-8859-14*
  • ISO-8859-15*
  • byte2be
  • byte2le
  • byte4be
  • byte4le
  • BASE64
  • HTML-ENTITIES
  • 7bit
  • 8bit
  • EUC-CN*
  • CP936
  • GB18030**
  • HZ
  • EUC-TW*
  • CP950
  • BIG-5*
  • EUC-KR*
  • UHC (CP949)
  • ISO-2022-KR
  • Windows-1251 (CP1251)
  • Windows-1252 (CP1252)
  • CP866 (IBM866)
  • KOI8-R*

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

** отмечает кодировки, доступные с PHP 5.4.0.

Любая запись в php.ini , которая принимает имя кодировки, может также использовать значения «auto» и «pass«. Функции mbstring, которые принимают имя кодировки, также могут использовать значение «auto«.

Если установлено значение «pass«, перекодировка не производится.

Если установлено значение «auto«, оно расширяется списком кодировок, определенным в NLS (настройках национального языка). Например, если NLS установлен в Japanese, предполагается, что значение будет из списка «ASCII,JIS,UTF-8,EUC-JP,SJIS«.

Источник

Оцените статью