Определение длины строки в PHP: байты, символы и графемные кластеры
Основные функции для измерения строк в PHP
Как определить длину строки в байтах с помощью функции strlen?
Функция strlen является самой простой и быстрой для получения длины строки в байтах. Она принимает строку и возвращает количество байт, которое она занимает в памяти. Это удобно при работе с бинарными данными, файлами, а также при проверке ограничений на размер ввода в байтах (например, поле VARCHAR(255) в базе данных MySQL, где 255 - это байты).
<?php
$str = "Hello";
echo strlen($str); // 5
?>Php длина символов (определение длины строки в php (strlen))
5
Важно: для строк в однобайтовых кодировках (ASCII) количество байт равно количеству символов. В многобайтовых кодировках (UTF-8) символы могут занимать от 1 до 4 байт, поэтому strlen вернёт значение, большее реального числа символов.
Как узнать длину строки в символах с учётом кодировки?
Функция mb_strlen из расширения mbstring позволяет получить количество символов в строке с указанием кодировки. Это правильный выбор для работы с текстом на естественных языках, где используются многобайтовые кодировки (UTF-8, UTF-16 и др.).
<?php
$str = "Привет";
echo mb_strlen($str, 'UTF-8'); // 6
?>
6
Если кодировка не указана, используется внутренняя кодировка (обычно UTF-8). Рекомендуется явно указывать кодировку, чтобы избежать неопределённости.
Как измерить длину строки с учётом графемных кластеров (например, эмодзи, символы с диакритиками)?
Функция grapheme_strlen из расширения intl возвращает количество графемных кластеров в строке. Графемный кластер - это визуальный символ, который может состоять из нескольких Unicode-кодовых точек (например, эмодзи семьи, буквы с ударениями).
<?php
$emoji = "????"; # последовательность ZWJ, 4 эмодзи + связи
echo grapheme_strlen($emoji); // 1
?>
1
Это полезно при подсчёте реального числа "видимых" символов в пользовательском вводе, например, при ограничении длины сообщения.
Как определить длину строки с помощью iconv_strlen?
Функция iconv_strlen также работает с многобайтовыми строками и требует указания кодировки. Она может быть альтернативой mb_strlen, если расширение mbstring недоступно, но iconv установлено.
<?php
$str = "Hello 世界";
echo iconv_strlen($str, 'UTF-8'); // 8 (7 букв + пробел)
?>
8
Обратите внимание: iconv_strlen ожидает, что строка корректна в указанной кодировке. Некорректная последовательность может привести к предупреждению или неверному результату.
Как выполнить измерение длины строки с помощью регулярных выражений или пользовательской функции?
В некоторых экзотических случаях, когда стандартные функции недоступны, можно написать собственную функцию для подсчёта символов, например, используя preg_match_all с модификатором u для работы с UTF-8.
<?php
$str = "Привет, мир!";
$count = preg_match_all('/./u', $str);
echo $count; // 12
?>
12
Этот метод менее эффективен, но может быть полезен, если нет других расширений. Однако он не учитывает графемные кластеры.
Расширенные примеры использования функций длины строки
Пример 1. Сравнение strlen, mb_strlen и grapheme_strlen на различных строках.
<?php
$strings = ['Hello', 'Привет', '日本語', '????', 'café'];
foreach ($strings as $s) {
echo "Строка: $s\n";
echo " strlen: " . strlen($s) . "\n";
echo " mb_strlen: " . mb_strlen($s, 'UTF-8') . "\n";
echo " grapheme_strlen: " . (function_exists('grapheme_strlen') ? grapheme_strlen($s) : 'N/A') . "\n";
}
?>
Строка: Hello strlen: 5 mb_strlen: 5 grapheme_strlen: 5 Строка: Привет strlen: 12 mb_strlen: 6 grapheme_strlen: 6 Строка: 日本語 strlen: 9 mb_strlen: 3 grapheme_strlen: 3 Строка: ???? strlen: 25 mb_strlen: 7 grapheme_strlen: 1 Строка: café strlen: 5 mb_strlen: 4 grapheme_strlen: 4
Пример 2. Проверка лимита в байтах для ввода в базу данных.
<?php
$input = "Пользовательский ввод";
$maxBytes = 20;
if (strlen($input) > $maxBytes) {
echo "Строка превышает лимит в $maxBytes байт";
} else {
echo "Строка укладывается в лимит";
}
// Вывод: Строка превышает лимит в 20 байт (строка занимает 38 байт)
?>
Строка превышает лимит в 20 байт
Пример 3. Использование mb_strlen с разными кодировками (на примере UTF-8 и Windows-1251).
<?php
$str = "Привет";
// Перекодируем строку в Windows-1251
$str1251 = iconv('UTF-8', 'Windows-1251', $str);
echo "Количество символов в UTF-8: " . mb_strlen($str, 'UTF-8') . "\n"; // 6
echo "Количество символов в Windows-1251: " . mb_strlen($str1251, 'Windows-1251') . "\n"; // 6
?>
Количество символов в UTF-8: 6 Количество символов в Windows-1251: 6
Пример 4. Обработка пустой строки и null (с учётом изменений в PHP 8.1+).
<?php
$empty = "";
$null = null;
echo "strlen(empty): " . strlen($empty) . "\n"; // 0
// Начиная с PHP 8.1 вызов strlen(null) выдаёт Deprecated, с PHP 9.0 - TypeError
if (is_string($null)) {
echo "strlen(null): " . strlen($null). "\n";
} else {
echo "null не является строкой\n";
}
?>
strlen(empty): 0 null не является строкой
Пример 5. Подсчёт графемных кластеров для ограничения длины сообщения с эмодзи.
<?php
$tweet = "Привет! ?????";
$maxGraphemes = 10;
if (grapheme_strlen($tweet) > $maxGraphemes) {
echo "Слишком длинное сообщение";
} else {
echo "Сообщение корректно";
}
// Результат: Сообщение корректно (всего 8 графем: 7 букв + восклицательный знак + пробел + 2 эмодзи? Уточним: grapheme_strlen("Привет! ?????") = 9? Нужно посчитать: П р и в е т ! пробел ? ???? -> 9 графем. Для 10 лимита проходит.
?>
Сообщение корректно
Пример 6. Собственная функция для подсчёта байт с обработкой многобайтовости (просто для демонстрации).
<?php
function customStrlen($str) {
$len = 0;
for ($i = 0; $i < strlen($str); $i++) {
$byte = ord($str[$i]);
if ($byte < 0x80) {
$len++;
$i += 0;
} elseif ($byte < 0xE0) {
$len++;
$i += 1;
} elseif ($byte < 0xF0) {
$len++;
$i += 2;
} else {
$len++;
$i += 3;
}
}
return $len;
}
$s = "Привет";
echo customStrlen($s); // 6
?>
6