лучший способ определить количество SMS, необходимых для отправки текста

Я ищу код / ​​lib в php, который я назову, и передам ему текст, и он скажет мне:

  1. Какую кодировку мне нужно использовать для отправки этого текста в виде SMS (7,8,16 бит)
  2. Сколько SMS-сообщений я буду использовать для отправки этого текста (он должен быть умным, чтобы считать «информацию о segmenation», как в http://ozekisms.com/index.php?owpn=612 )

есть ли у вас какие-либо идеи о существовании какого-либо кода / lib, который сделает это для меня?

Опять же, я не ищу отправки SMS или конвертации SMS, просто чтобы дать мне информацию о тексте

Обновить:

Хорошо, я сделал код ниже и, похоже, работает нормально, дайте мне знать, если у вас есть лучший / оптимизированный код / ​​решение / lib

$text = '\@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ -./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà^{}[~]|€' ; //"\\". //'"';//' '; print $text . "\n"; print isGsm7bit($text). "\n"; print getNumberOfSMSsegments($text). "\n"; function getNumberOfSMSsegments($text,$MaxSegments=6){ /* http://en.wikipedia.org/wiki/SMS Larger content (concatenated SMS, multipart or segmented SMS, or "long SMS") can be sent using multiple messages, in which case each message will start with a user data header (UDH) containing segmentation information. Since UDH is part of the payload, the number of available characters per segment is lower: 153 for 7-bit encoding, 134 for 8-bit encoding and 67 for 16-bit encoding. The receiving handset is then responsible for reassembling the message and presenting it to the user as one long message. While the standard theoretically permits up to 255 segments,[35] 6 to 8 segment messages are the practical maximum, and long messages are often billed as equivalent to multiple SMS messages. See concatenated SMS for more information. Some providers have offered length-oriented pricing schemes for messages, however, the phenomenon is disappearing. */ $TotalSegment=0; $textlen = mb_strlen($text); if($textlen==0) return false; //I can see most mobile devices will not allow you to send empty sms, with this check we make sure we don't allow empty SMS if(isGsm7bit($text)){ //7-bit $SingleMax=160; $ConcatMax=153; }else{ //UCS-2 Encoding (16-bit) $SingleMax=70; $ConcatMax=67; } if($textlen<=$SingleMax){ $TotalSegment = 1; }else{ $TotalSegment = ceil($textlen/$ConcatMax); } if($TotalSegment>$MaxSegments) return false; //SMS is very big. return $TotalSegment; } function isGsm7bit($text){ $gsm7bitChars = "\\\@£\$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà^{}[~]|€"; $textlen = mb_strlen($text); for ($i = 0;$i < $textlen; $i++){ if ((strpos($gsm7bitChars, $text[$i])==false) && ($text[$i]!="\\")){return false;} //strpos not able to detect \ in string } return true; } 

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

    Это проблемы:

    • Вам нужно указать текущую строковую кодировку mb_string, иначе это может быть неправильно собрано
    • В 7-битной кодировке GSM для символов Basic Charset Extended (^ {} \ [~] | €) требуется 14 бит для кодирования, поэтому они считаются двумя символами.
    • В кодировке UCS-2 вы должны быть осторожны с emoji и другими персонажами за пределами 16-битного BMP, потому что …
    • GSM с UCS-2 подсчитывает 16-битные символы, поэтому, если у вас есть символ 💩 (U + 1F4A9), а ваш оператор и телефон скрытно поддерживают UTF-16, а не только UCS-2, он будет закодирован как суррогатная пара 16-разрядные символы в UTF-16 и, таким образом, считаются ДВА 16-разрядными символами в соответствии с длиной строки. mb_strlen будет считать это только одним символом.

    Как подсчитать 7-битные символы:

    До сих пор я пришел к следующему: считать 7-битные символы:

     // Internal encoding must be set to UTF-8, // and the input string must be UTF-8 encoded for this to work correctly protected function count_gsm_string($str) { // Basic GSM character set (one 7-bit encoded char each) $gsm_7bit_basic = "@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà"; // Extended set (requires escape code before character thus 2x7-bit encodings per) $gsm_7bit_extended = "^{}\\[~]|€"; $len = 0; for($i = 0; $i < mb_strlen($str); $i++) { if(mb_strpos($gsm_7bit_basic, $str[$i]) !== FALSE) { $len++; } else if(mb_strpos($gsm_7bit_extended, $str[$i]) !== FALSE) { $len += 2; } else { return -1; // cannot be encoded as GSM, immediately return -1 } } return $len; } 

    Как считать 16-разрядные символы:

    • Преобразуйте строку в представление UTF-16 (чтобы сохранить символы mb_convert_encoding($str, 'UTF-16', 'UTF-8') с mb_convert_encoding($str, 'UTF-16', 'UTF-8') .
      • не конвертировать в UCS-2, поскольку это с mb_convert_encoding )
    • count(unpack('C*', $utf16str)) байты со count(unpack('C*', $utf16str)) и разделите на два, чтобы получить количество 16-разрядных символов UCS-2, которые подсчитываются в сторону многострочной длины GSM

    * caveat emptor, слово для подсчета байтов:

    • Не используйте strlen для подсчета количества байтов. Хотя это может сработать, strlen часто перегружается в установках PHP с поддержкой многобайтовых версий, а также является кандидатом на изменение API в будущем
    • Избегайте mb_strlen($str, 'UCS-2') . В то время как он в настоящее время работает и правильно вернет 2 для кучи символа poo (поскольку он выглядит как два 16-битных символа UCS-2), его mb_convert_encoding является mb_convert_encoding при преобразовании с> 16-бит в UCS-2 , Кто скажет, что mb_strlen не будет убыточным в будущем?
    • Избегайте mb_strlen($str, '8bit') / 2 . Он также работает и рекомендуется в комментарии к документам PHP как способ подсчета байтов. Но ИМО страдает от той же проблемы, что и вышеупомянутая техника UCS-2.
    • Это оставляет самый безопасный текущий способ (IMO) как unpack в байтовый массив и подсчет этого.

    Итак, как это выглядит?

     // Internal encoding must be set to UTF-8, // and the input string must be UTF-8 encoded for this to work correctly protected function count_ucs2_string($str) { $utf16str = mb_convert_encoding($str, 'UTF-16', 'UTF-8'); // C* option gives an unsigned 16-bit integer representation of each byte // which option you choose doesn't actually matter as long as you get one value per byte $byteArray = unpack('C*', $utf16str); return count($byteArray) / 2; } 

    Объединяя все это:

     function multipart_count($str) { $one_part_limit = 160; // use a constant ie GSM::SMS_SINGLE_7BIT $multi_limit = 153; // again, use a constant $max_parts = 3; // ... constant $str_length = count_gsm_string($str); if($gsm_count === -1) { $one_part_limit = 70; // ... constant $multi_limit = 67; // ... constant $str_length = count_ucs2_string($str); } if($str_length <= $one_part_limit) { // fits in one part return 1; } else if($str_length > ($max_parts * $multi_limit) { // too long return -1; // or throw exception, or false, etc. } else { // divide the string length by multi_limit and round up to get number of parts return ceil($str_length / $multi_limit); } } 

    Повернул это в библиотеку …

    https://bitbucket.org/solvam/smstools

    Лучшее решение, которое у меня есть до сих пор:

     $text = '\@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ -./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà^{}[~]|€' ; //"\\". //'"';//' '; print $text . "\n"; print isGsm7bit($text). "\n"; print getNumberOfSMSsegments($text). "\n"; function getNumberOfSMSsegments($text,$MaxSegments=6){ /* http://en.wikipedia.org/wiki/SMS Larger content (concatenated SMS, multipart or segmented SMS, or "long SMS") can be sent using multiple messages, in which case each message will start with a user data header (UDH) containing segmentation information. Since UDH is part of the payload, the number of available characters per segment is lower: 153 for 7-bit encoding, 134 for 8-bit encoding and 67 for 16-bit encoding. The receiving handset is then responsible for reassembling the message and presenting it to the user as one long message. While the standard theoretically permits up to 255 segments,[35] 6 to 8 segment messages are the practical maximum, and long messages are often billed as equivalent to multiple SMS messages. See concatenated SMS for more information. Some providers have offered length-oriented pricing schemes for messages, however, the phenomenon is disappearing. */ $TotalSegment=0; $textlen = mb_strlen($text); if($textlen==0) return false; //I can see most mobile devices will not allow you to send empty sms, with this check we make sure we don't allow empty SMS if(isGsm7bit($text)){ //7-bit $SingleMax=160; $ConcatMax=153; }else{ //UCS-2 Encoding (16-bit) $SingleMax=70; $ConcatMax=67; } if($textlen<=$SingleMax){ $TotalSegment = 1; }else{ $TotalSegment = ceil($textlen/$ConcatMax); } if($TotalSegment>$MaxSegments) return false; //SMS is very big. return $TotalSegment; } function isGsm7bit($text){ $gsm7bitChars = "\\\@£\$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà^{}[~]|€"; $textlen = mb_strlen($text); for ($i = 0;$i < $textlen; $i++){ if ((strpos($gsm7bitChars, $text[$i])==false) && ($text[$i]!="\\")){return false;} //strpos not able to detect \ in string } return true; }