Оглавление

15.10. Функции для работы со строками в кодировке UTF-8

В однобайтовых кодировках символ кодируется одним байтом. Первые 7 бит позволяют закодировать 128 символов, соответствующих кодировке ASCII. Символы, имеющие код меньше 33, являются специальными, например, нулевой символ, символ переноса строки, табуляция и т. д. Получить остальные символы позволяет следующий код:

for ($i=33; $i<128; $i++) {
   echo $i . " =&gt; " . chr($i) . "<br>";
}


Коды этих символов одинаковы практически во всех однобайтовых кодировках. Восьмой бит предназначен для кодирования символов национальных алфавитов. Таким образом, однобайтовые кодировки позволяют закодировать всего 256 символов.


К любому символу строки в однобайтовой кодировке (например, windows-1251 или KOI8-R) можно обратиться как к элементу массива. Достаточно указать его индекс в квадратных скобках. Нумерация начинается с нуля:

$X = 'Привет'; // Кодировка windows-1251 или KOI8-R
echo $X[0];


В кодировке UTF-8 один символ может кодироваться несколькими байтами. Первые 128 символов соответствуют кодировке ASCII и кодируются всего одним байтом. Остальные символы кодируются переменным количеством байт от двух до шести (на практике только до четырех). Буквы русского алфавита и некоторых другие европейские языки кодируются двумя байтами. По этой причине использовать обычные строковые функции нельзя. В данном разделе мы рассмотрим функции, которые можно использовать при работе с кодировкой UTF-8.


Так как в кодировке UTF-8 один символ может кодироваться несколькими байтами, то обратиться к символу как к элементу массива можно только после перекодировки. Тем не менее к символам кодировки ASCII мы можем обратиться как к элементам массива, так как они кодируются одним байтом:

$X = 'String'; // Кодировка UTF-8
echo $X[0]; // Выведет: S


Если необходимо обращаться к любым символам как к элементам массива, то можно воспользоваться следующим кодом: (1)

<?php
header('Content-Type: text/html; charset=utf-8');
$str = 'Строка';
$count = mb_strlen($str, 'UTF-8');
$arr = array();
for ($i=0; $i<$count; $i++) {
   $arr[] = mb_substr($str, $i, 1, 'UTF-8');
}
echo '<pre>';
print_r($arr);
echo '</pre>';
?>

 

В инструкции Программное обеспечение Web-сервера мы настраивали сервер на кодировку windows-1251. Поэтому при работе с UTF-8 необходимо указывать кодировку явным образом. Шаблон программы будет выг|лядеть так:

<?php
header('Content-Type: text/html; charset=utf-8');
// Сюда вставляем примеры из этого раздела
?>


Notepad++Кроме того, сам файл необходимо сохранить в кодировке UTF-8. Использовать для этого Блокнот нельзя, так как он вставляет в начало файла служебные символы, называемые сокращенно BOM (Byte Order Mark, метка порядка байтов). Для кодировки UTF-8 эти символы не являются обязательными и не позволят нам установить заголовки ответа сервера с помощью функции header(). Для сохранения файлов следует использовать программу Notepad++. В меню Кодировки устанавливаем флажок Кодировать в UTF-8 (без ВОМ), а затем набираем код. В случае копирования кода через буфер обмена советую вначале сохранить пустой файл в кодировке UTF-8 без ВОМ, вставить код из буфера обмена, а затем сохранить файл с помощью соответствующеи кнопки на панели инструментов.


Для работы со строками в кодировке UTF-8 (а также с другими кодировками) предназначены следующие функции:
□ mb_strlen(<Строка>[, <Кодировка>]) возвращает количество символов в строке:

$str = 'Строка';
echo mb_strlen($str, 'UTF-8'); // Выведет: 6

 

□ iconv_strlen(<Строка>[, <Кодировка>]) возвращает количество символов в строке:

$str = 'Строка';
echo iconv_strlen($str, 'UTF-8'); // Выведет: 6


□ strlen(<Строка>) возвращает количество байт в строке. Так как в однобайтовых кодировках один символ описывается одним байтом, функция strlen() возвращает количество символов. Для многобайтовых кодировок функция возвращает именно количество байт:

$str = 'Строка UTF-8';
echo strlen($str); // Выведет: 18
$str = iconv('UTF-8', 'windows-1251', $str);
echo strlen($str); // Выведет: 12


Почему же мы получили 18 байт, а не 24? Все дело в том, что в кодировке UTF-8 первые 128 символов кодируются одним байтом, а все последующие символы кодируется несколькими байтами. Каждый символ в слове "Строка" занимает по 2 байта, а в последующей части строки (" UTF-8") каждый символ занимает один байт. Итого 6 умножить на 2 плюс 6 равно 18 байт. (2)

 

□ mb_substr() возвращает подстроку указанной длины, начиная с заданной позиции. Если длина не указана, то возвращается подстрока, начиная с заданной позиции и до конца строки. Функция имеет следующий формат:
mb_substr(<Строка>, <Начальная позиция>[, <Длина>[,
          <Кодировка>]]);
Пример 1:

$str = 'Строка';
$str1 = mb_substr($str, 0, 1, 'UTF-8');
echo $str1; // Выведет: C


Пример 2:

mb_internal_encoding('UTF-8'); // Установка кодировки
$str = 'Строка';
$str2 = mb_substr($str, 1);
echo $str2; // Выведет: трока


Для настройки кодировки необходимо указать ее в четвертом параметре функции mb_substr() или отдельно в функции mb_internal_encoding();
□ iconv_substr() возвращает подстроку указанной длины, начиная с заданной позиции. Если длина не указана, то возвращается подстрока, начиная с заданной позиции и до конца строки. Функция имеет следующий формат:
iconv_substr(<Строка>, <Начальная позиция>[, <Длина>[,
             <Кодировка>]]);
Пример 1:

$str = 'Строка';
$str1 = iconv_substr($str, 0, 1, 'UTF-8');
echo $str1; // Выведет: C


Пример 2:

iconv_set_encoding('internal_encoding', 'UTF-8');
$str = 'Строка';
$str2 = iconv_substr($str, 1);
echo $str2; // Выведет: трока

 

Для настройки кодировки необходимо указать ее в четвертом параметре функции iconv_substr() или отдельно в функции iconv_set_encoding();
□ mb_encode_mimeheader() —   позволяет  закодировать  текст  с  помощью методов base64 или Quoted-Printable. Функция имеет следующий формат:
mb_encode_mimeheader(<Строка>, [<Кодировка>[, 
   <Метод кодирования>[, <Символ переноса строк>]]]);

 

Если параметр <кодировка> не указан, то используется значение, указанное в функции mb_internal_encoding(). Как показывает практика, указывать кодировку В функции mb_internal_encoding() нужно обязательно. Параметр <метод кодирования> может принимать значения "B" (base64) или "Q" (Quoted-Printable). Если параметр не указан, то используется значение "В". Параметр <символ переноса строк> задает символ для разделения строк. По умолчанию предполагается комбинация "\r\n". Пример:

mb_internal_encoding('UTF-8');
$tema = 'Сообщение';
echo mb_encode_mimeheader($tema);
// Выведет: =?UTF-8?B?0KHQvtC+0LHRidC10L3QuNC1?=

 

Для изменения регистра символов предназначены следующие функции:
□ mb_strtoupper(<Строка>[, <Кодировка>]) заменяет все символы строки соответствующими прописными буквами:

$str = 'очень длинная строка';
echo mb_strtoupper($str, 'UTF-8');
// Выведет: ОЧЕНЬ ДЛИННАЯ СТРОКА


□ mb_strtolower(<Строка>[, <Кодировка>]) заменяет все символы строки соответствующими строчными буквами:

$str = 'ОЧЕНЬ длинная строка';
echo mb_strtolower($str, 'UTF-8');
// Выведет: очень длинная строка


□ mb_convert_case(<Строка>, <Режим>[, <Кодировка>]) Преооразует регистр символов в зависимости от значения второго параметра. Параметр <Режим> может принимать следующие значения:
•  MB_CASE_UPPER — заменяет все символы строки соответствующими прописными буквами;

•  MB_CASE_LOWER— заменяет все символы строки соответствующими строчными буквами;
•  MB_CASE_TITLE — делает первые символы всех слов прописными.

 

Примеры:

$str = 'ОЧЕНЬ длинная строка';
echo mb_convert_case($str, MB_CASE_UPPER, 'UTF-8');
// Выведет: ОЧЕНЬ ДЛИННАЯ СТРОКА
echo '<br>';
echo mb_convert_case($str, MB_CASE_LOWER, 'UTF-8');
// Выведет: очень длинная строка
echo '<br>';
echo mb_convert_case($str, MB_CASE_TITLE, 'UTF-8');
// Выведет: Очень Длинная Строка
echo '<br>';
mb_internal_encoding('UTF-8'); // Установка кодировки
echo mb_convert_case($str, MB_CASE_UPPER);
// Выведет: ОЧЕНЬ ДЛИННАЯ СТРОКА

Для поиска в строке используются следующие функции:
□ mb_strpos() ищет подстроку в строке. Возвращает номер позиции, с которой начинается вхождение подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. Функция зависит от регистра символов. Имеет следующий формат:
mb_strpos(<Строка>, <Подстрока>[, <Начальная позиция поиска>[,
          <Кодировка>]]);
Если начальная позиция не указана, то поиск будет производиться с начала строки:

echo mb_strpos('Привет', 'ри', 0, 'UTF-8'); // Выведет: 1
mb_internal_encoding('UTF-8'); // Установка кодировки
if (mb_strpos('Привет', 'При') !== false) echo 'Найдено';
// Выведет: Найдено
else echo 'Не найдено';


□ iconv_strpos()ищет подстроку в строке. Возвращает номер позиции, с которой начинается вхождение подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. Функция зависит от регистра символов. Если начальная позиция не указана, то поиск будет производиться с начала строки. Функция имеет следующий формат:
iconv_strpos(<Строка>, <Подстрока>[, <Начальная  позиция  поиска>[,
             <Кодировка>]]);
Примеры:

echo iconv_strpos('Привет', 'ри', 0, 'UTF-8'); // Выведет: 1
if (iconv_strpos('Привет', 'При', 0, 'UTF-8') !== false) 
echo 'Найдено';
// Выведет: Найдено
else echo 'Не найдено';


□ mb_stripos() ищет подстроку в строке. Возвращает номер позиции, с которой начинается вхождение подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. В отличие от функции mb_strpos() не зависит от регистра символов. Имеет следующий формат:

mb_stripos(<Строка>, <Подстрока>[, <Начальная позиция поиска>[,
           <Кодировка>]]);

 

Пример:

echo mb_stripos('Привет', 'РИ', 0, 'UTF-8'); // Выведет: 1


Если начальная позиция не указана, то поиск будет производиться с начала строки;
□ mb_strrpos() ищет подстроку в строке. Возвращает позицию последнего вхождения подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. Функция зависит от регистра символов. Имеет следующий формат:
mb_strrpos(<Строка>, <Подстрока>[, <Начальная позиция поиска>[,
           <Кодировка>]]);
Если начальная позиция не указана, то поиск будет производиться с начала строки:

echo mb_strrpos('ерпарверпр', 'ер', 0, 'UTF-8'); // Выведет: 6


□ iconv_strrpos() ищет подстроку в строке. Возвращает позицию последнего вхождения подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. Функция зависит от регистра символов.

 

Имеет следующий формат:
iconv_strrpos(<Строка>, <Подстрока>[, <Кодировка>]);
Пример:

echo iconv_strrpos('ерпарверпр', 'ер', 'UTF-8'); // Выведет: 6


□ mb_strripos() ищет подстроку в строке. Возвращает позицию последнего вхождения подстроки в строку. Если подстрока в строку не входит, то функция возвращает false. В отличие от функции mb_strrpos() не зависит от регистра символов. Имеет следующий формат:
mb_strripos(<Строка>, <Подстрока>[, <Начальная позиция поиска>[,
         <Кодировка>]]);
Если начальная позиция не указана, то поиск будет производиться с начала строки:

echo mb_strripos('ерпарверпр', 'ЕР', 0, 'UTF-8'); // Выведет: 6


□ mb_substr_count()   возвращает число вхождений подстроки в строку.

Функция зависит от регистра символов. Имеет следующий формат:
mb_substr_count(<Строка>, <Подстрока>[, <Кодировка>]);
 

 

Пример:

echo mb_substr_count('ерпаерпр', 'ер', 'UTF-8'); // Выведет: 2

 

Как вы уже наверняка заметили, параметр <кодировка> во всех этих функциях является необязательным.
Если параметр не указан, то:
□    при использовании функций, начинающихся с префикса "mb_", используется значение директивы mbstring.internal_encoding или значение, указанное в функции mb_internal_encoding();
□    при использовании функций, начинающихся с префикса "iconv_", используется значение директивы iconv.internal_encoding или значение, указанное в функции iconv_set_encoding().

 

Для  преобразования  кодировок можно использовать функции  iconv()   и mb_convert_encoding() (см. разд. 15.7).
Некоторые обычные строковые функции также можно использовать при работе с кодировкой UTF-8:
□ str_replace() — для замены в строке;
□ htmlspecialchars() — для замены специальных символов их HTML-эквивалентами. Кодировка указывается в третьем параметре;
□ trim(), ltrim() и rtrim() — для удаления пробельных символов в начале и (или) конце строки. Если во втором параметре указать список символов (например, русских букв), то функции будут работать некорректно;
□ addslashes() — для добавления защитных слэшей перед специальными символами;
□ stripslashes() — для удаления защитных слэшей.

 
Функции  trim(), addslashes() и stripslashes() можно  использовать, так как они удаляют (или добавляют) символы, которые в UTF-8 кодируются одним байтом. Все эти функции мы уже рассматривали в разд. 15.1. Кроме перечисленных функций для кодирования и шифрования строк можно использовать функции, рассмотренные в разд. 15.6.

 

Если необходимо использовать регулярные выражения для поиска или замены в строке, то следует применять Perl-совместимые регулярные выражения (PCRE). Так как мы работаем с кодировкой UTF-8, то в параметре <модификатор> обязательно должен присутствовать модификатор u. В качестве примера удалим все русские буквы из строки:  (3)

$str = 'строка1строка2строка3';
echo preg_replace('#[а-яё]#isu', '', $str); // 123

 

 

Если в этом примере модификатор u не указать, то будет удален один байт из каждого двухбайтового символа и в итоге в строке появятся "квадратики" или знаки вопроса.

 

Примечания:
  • Для работы PHP с кодировкой UTF-8 необходимо, чтобы в конфигурационном файле была подключена библиотека php_mbstring.dll.
  • Если в конфигурационном файле php.ini директива mbstring.func_overload равна 2 или 7, то функция strlen() полностью эквивалентна функции mb_strlen(). Это означает, что функция strlen() будет возвращать количество символов, а не байт.
  • Регистр модификатора u имеет значение.
Комментарии принадлежат их авторам. Мы не несем ответственности за их содержание.
Отправитель Нити