Статьи

Работа с многобайтовыми строками

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

Основы

Все мы знаем, что «бит» — это вещь, которая может быть 0 или 1 и ничем иным, а «байт» — это группа из восьми последовательных битов. Поскольку в байте имеется восемь таких двойных значений, один байт может быть сконфигурирован в общей сложности 256 различных шаблонов (от 2 до степени 8). С каждым возможным 8-битным шаблоном можно связать разные символы.

Соедините эти байты в разных порядках, и вы получите некоторое общение. Это не обязательно разумно, это зависит от того, кто на каждом конце, но это общение. Пока мы можем выразить символы языка 256 уникальными символами или меньше, мы настроены.

Но что, если мы не можем выразить язык всего 256 символами? Или что если нам нужно выразить несколько языков в одном документе? Сегодня, когда мы оцифровываем все, что можем найти, 256 символов далеко не достаточно. К счастью, были разработаны схемы персонажей, которые более соответствуют требованиям. Эти новые наборы суперсимволов используют от одного до четырех байтов для определения символов.

Большая собака в сегодняшней сцене кодирования символов — Unicode, схема, которая использует несколько байтов для представления символов. Он был разработан Консорциумом Юникод и существует несколько его версий: UTF-32, который используется на кораблях класса Dreadnaught, UTF-16, который используется на Star Trek: Into Darkness Enterprise, и UTF-8, который является тем, что большинство из нас в реальном мире должны использовать для наших веб-приложений.

Как я уже сказал, Unicode (включая UTF-8) использует многобайтовые конфигурации для представления символов. UTF-8 использует от одного до четырех байтов для создания 1,112,064 шаблонов, представляющих разные символы. Эти «широкие символы» занимают больше места, но UTF-8 имеет тенденцию быстрее обрабатывать, чем некоторые другие схемы кодирования.

Почему все говорят о UTF-8? Частично это горячие модели, которые были выделены в рекламных роликах поддержки UTF-8 на ESPN и TCM, но в основном это потому, что UTF-8 имитирует ASCII, и если у вас нет специальных символов, он точно отслеживает ASCII.

И это влияет на PHP Как?

Я знаю, о чем ты думаешь. Мне просто нужно установить набор символов в моих метатегах на «UTF-8», и все будет хорошо. Но это не правда.

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

И во-вторых, даже если у вас есть PHP под контролем, могут быть проблемы. Заголовки HTTP, охватывающие ваше сообщение, также содержат идентификацию набора символов, которая переопределяет то, что находится в метатеге вашей страницы.

Итак, как PHP работает с многобайтовыми символами? Есть две функциональные группы, которые влияют на многобайтовые строки.

Первый — это iconv . С 5.0 это стало частью языка по умолчанию, способ преобразовать один набор символов в другое представление набора символов. Это не то, о чем мы будем говорить в этой статье.

Второй — поддержка многобайтовых данных, серия команд с префиксом «mb_». Существует ряд этих команд, и краткий обзор показывает, что некоторые из них относятся к определению, являются ли символы подходящими на основе заданной схемы кодирования, а другие — это функции, ориентированные на поиск, аналогичные тем, которые являются частью регулярных выражений PHP, но которые ориентированы вокруг многобайтовых функций.

Включение многобайтовой поддержки PHP

Многобайтовая поддержка не является функцией PHP по умолчанию, но она также не требует загрузки дополнительных библиотек или расширений; это просто требует некоторой реконфигурации. К сожалению, если вы используете размещенную версию PHP, это может быть не то, что вы можете сделать.

Посмотрите на вашу конфигурацию, используя phpinfo() Прокрутите примерно на полпути вниз, и появится раздел с надписью «mbstring». Это покажет вам, включены ли основные функции. Для получения информации о том, как включить это, вы можете обратиться к руководству . Короче говоря, вы включаете функции mb с помощью параметра времени компиляции --enable-mbstringmbstring-encoding_translation

Конечным решением, конечно же, является PHP 6, поскольку он будет использовать библиотеки ICU IBM (пожалуйста, все снимают свои шариковые крышки), чтобы обеспечить встроенную поддержку многобайтовых наборов символов. Все, что нам нужно сделать, это сидеть сложа руки и ждать, приятель икра? Но до тех пор, проверьте многобайтовую поддержку, которая доступна сейчас.

Многобайтовые строковые команды

Возможно, есть 53 различных многобайтовых строковых команды. Также возможно, что их 54. В некотором смысле я потерял счет, но вы поняли. Само собой разумеется, что мы не собираемся проходить каждый из них, но только для целей, давайте кратко рассмотрим несколько.

mb_check_encoding

Функция mb_check_encoding() Функция не сообщает вам, как закодирована строка (или для каких схем она будет работать), но она сообщает вам, будет ли она работать для указанной схемы.

 <?php
$string = 'u4F60u597Du4E16u754C';
$string = json_decode('"' . $string . '"');
$valid = mb_check_encoding($string, 'UTF-8');
echo ($valid) ? 'valid' : 'invalid';

Вы можете найти список поддерживаемых кодировок в руководстве по PHP.

mb_strlen

Функция strlen() Для ASCII, где каждый символ представляет собой один байт, это прекрасно работает для определения количества символов. С многобайтовыми строками вам нужно использовать mb_strlen()

 <?php
$string = 'u4F60u597Du4E16u754C';
$string = json_decode('"' . $string . '"');

echo strlen($string); // outputs 12 – wrong!
echo mb_strlen($string, 'UTF-8'); // outputs 4

mb_ereg_search

Функция mb_ereg_search() Но есть несколько предостережений — вам нужно указать схему кодирования с помощью функции mb_regex_encoding()mb_ereg_search_init()

 <?php
// specify the encoding scheme
mb_regex_encoding('UTF-8');

// specify haystack and search
$string = 'u4F60u597Du4E16u754C';
$string = json_decode('"' . $string . '"');

$pattern = 'u754C';
$pattern = json_decode('"' . $pattern . '"');

mb_ereg_search_init($string, $pattern);

// finally we can perform the search 
$result = mb_ereg_search();
echo ($result) ? "found" : "not found";

Достаточно?

Я не знаю как вы, но я думаю, что миру действительно нужны более простые вещи. К сожалению, многобайтовая обработка не сможет удовлетворить эту потребность. Но сейчас это то, что вы не можете игнорировать. Есть моменты, когда вы не сможете выполнить обычную обработку строк PHP (потому что вы пытаетесь сделать это над символами, которые превышают нормальный диапазон ASCII (U + 0000 — U + 00FF)). А это значит, что вы должны использовать функции, ориентированные на mb_.

Хотите узнать больше? Серьезно, вы делаете? Я честно думал, что это отпугнет тебя. Я не был готов к этому. И мое время истекло. Ваша лучшая ставка? Ознакомьтесь с руководством по PHP . Ох, и попробуйте вещи. Там нет замены для реального опыта использования чего-либо.

Изображение через Fotolia