У меня есть следующая функция с сайта php.net, чтобы определить количество байтов в строке ASCII и UTF-8:
<?php /** * Count the number of bytes of a given string. * Input string is expected to be ASCII or UTF-8 encoded. * Warning: the function doesn't return the number of chars * in the string, but the number of bytes. * * @param string $str The string to compute number of bytes * * @return The length in bytes of the given string. */ function strBytes($str) { // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT // Number of characters in string $strlen_var = strlen($str); // string bytes counter $d = 0; /* * Iterate over every character in the string, * escaping with a slash or encoding to UTF-8 where necessary */ for ($c = 0; $c < $strlen_var; ++$c) { $ord_var_c = ord($str{$d}); switch (true) { case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): // characters U-00000000 - U-0000007F (same as ASCII) $d++; break; case (($ord_var_c & 0xE0) == 0xC0): // characters U-00000080 - U-000007FF, mask 110XXXXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 $d+=2; break; case (($ord_var_c & 0xF0) == 0xE0): // characters U-00000800 - U-0000FFFF, mask 1110XXXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 $d+=3; break; case (($ord_var_c & 0xF8) == 0xF0): // characters U-00010000 - U-001FFFFF, mask 11110XXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 $d+=4; break; case (($ord_var_c & 0xFC) == 0xF8): // characters U-00200000 - U-03FFFFFF, mask 111110XX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 $d+=5; break; case (($ord_var_c & 0xFE) == 0xFC): // characters U-04000000 - U-7FFFFFFF, mask 1111110X // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 $d+=6; break; default: $d++; } } return $d; } ?>
Однако, когда я пробую это с русским (например, По своей природе компьютеры могут работать лишь с числами. И для того, чтобы они могли хранить в памяти буквы или другие символы, каждому такому символу должно быть поставлено в соответствие число.
). Кажется, он не возвращает правильное количество байтов.
Оператор switch использует условие по умолчанию. Любые идеи, почему русские символы не будут работать так, как ожидалось? Или были бы лучшие варианты для этого.
Я спрашиваю об этом, поскольку мне нужно сократить строку UTF-8 до определенного количества байтов. т.е. я могу отправить только макс. из 169 байтов данных JSON в iPhone APNS в моей ситуации (исключая другие пакетные данные).
Ссылка: PHP strlen – Руководство (Комментарий Паоло от 10 января 2007 г. 03:58)
Я спрашиваю об этом, поскольку мне нужно сократить строку utf-8 до определенного количества байтов.
mb_strcut()
делает именно это, хотя вы, возможно, не сможете сказать из едва понятной документации.
strlen () возвращает количество байтов.
Сокращение многобайтовой строки до определенного количества байтов – отдельная задача. Вам нужно будет позаботиться о том, чтобы не вырезать строку в середине многобайтовой последовательности по мере ее сокращения.
Другая вещь, которую вам нужно обработать, это то, что когда вы помещаете строку в json-нотацию, ей может понадобиться больше байтов для представления ее как json. Например, если ваша строка содержит символ двойной кавычки. Он должен быть экранирован, а символ обратной косой черты добавит один байт. Есть и другие персонажи, которых тоже нужно избегать. Точка, она может стать больше. Я предполагаю, что ограничение байта находится на общей полезной нагрузке json, поэтому вам нужно учитывать сам синтаксис json, а также любое экранирование, которое json будет налагать на вашу строку.
Неоптимизированный, любопытный хакерский способ сделать это – нарезать строку, скажем, на 5 байт больше вашего предела, используя substr (). Теперь используйте mb_strlen (), чтобы получить количество символов, и mb_substr (), чтобы удалить последний символ. Теперь кодируем его как json и измеряем байты через strlen (). Введите цикл, который продолжает измельчать последний символ, используя mb_substr (), кодирует как json и снова измеряет байты с помощью strlen (). Цикл завершается, когда количество байтов допустимо.
В PHP 5 mb_strlen
должен возвращать количество символов; и strlen
должен возвращать количество байтов.
Например, эта часть кода:
$string = 'По своей природе компьютеры могут работать лишь с числами. И для того, чтобы они могли хранить в памяти буквы или другие символы, каждому такому символу должно быть поставлено в соответствие число'; echo mb_strlen($string, 'UTF-8') . '<br />'; echo strlen($string);
Должен получить следующий результат:
196 359
В качестве побочного элемента: это то, что изменит PHP 6: PHP 6 будет использовать Unicode по умолчанию, что означает, что strlen
должен в PHP 6 возвращать количество символов, а не количество байтов больше.
Если вы хотите найти длину байта многобайтовой строки при использовании строк mbstring.func_overload 2 и UTF-8, вы можете использовать следующее:
mb_strlen($utf8_string, 'latin1');
Count of Bytes <> Длина строки!
для получения счета байта вы можете использовать (php4,5) strlen. для получения длины в кодировке unicode (utf8 encoded) вы можете использовать mb_strlen (позаботьтесь о перегрузке функции из этого расширения), или вы можете просто подсчитать все байты, которые не имеют 8-го бита.
8-й бит означает, что для этого unicodechar приходит по крайней мере еще один байт от входа.