首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检测发送文本所需SMS数量的最佳方法

检测发送文本所需SMS数量的最佳方法
EN

Stack Overflow用户
提问于 2011-12-01 23:25:38
回答 3查看 6.3K关注 0票数 10

我正在寻找一个代码/lib in php,我将调用它并将文本传递给它,它会告诉我:

要将此文本作为SMS (7,8,16位) http://ozekisms.com/index.php?owpn=612) (7,8,16位)

  • 发送所需的编码是什么?

您知道有什么代码/库可以为我做到这一点吗?

再说一次,我不想发送短信或转换短信,只是为了给我关于文本的信息。

更新:

好的,我做了下面的代码,它看起来很好,让我知道你是否有更好的/优化的代码/解决方案/库

代码语言:javascript
复制
$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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-03 20:10:02

到目前为止,我能找到的最好的解决方案是:

代码语言:javascript
复制
$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;
}
票数 4
EN

Stack Overflow用户

发布于 2015-09-04 03:54:30

我在这里添加了一些额外的信息,因为前面的答案并不完全正确。

这些是问题所在:

  • 您需要将当前的字符串编码指定为mb_string,否则可能会错误地收集7位GSM编码中的
  • ,基本字符集扩展字符(^{}[~]\欧元)要求每个字符编码14位,因此每个字符都算作两个字符。在UCS-2编码中的
  • ,您必须对16位BMP以外的表情符号和其他字符保持警惕,因为.
  • GSM具有UCS-2计数16位字符,所以如果您有一个字符(U+1F4A9),你的载波和电话暗中支持UTF-16,而不仅仅是UCS-2,它将被编码为UTF-16中由16位字符组成的代理项对,因此被计算为两个16位字符与您的字符串长度。mb_strlen只将此计算为单个字符。

如何计算7位字符:

到目前为止,我想出的是以下7位字符的计数:

代码语言:javascript
复制
// 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++) {
        $c = mb_substr($str, i, 1);
        if(mb_strpos($gsm_7bit_basic, $c) !== FALSE) {
            $len++;
        } else if(mb_strpos($gsm_7bit_extended, $c) !== FALSE) {
            $len += 2;
        } else {
            return -1; // cannot be encoded as GSM, immediately return -1
        }
    }

    return $len;
}

如何计算16位字符:

mb_convert_encoding($str, 'UTF-16', 'UTF-8').

  • do
  • 将字符串转换为UTF-16表示形式(为了保留带有GSM而不是的符号字符,将其转换为UCS-2,因为这是有损于使用count(unpack('C*', $utf16str))mb_convert_encoding)
  • Count字节,然后除以2,得到计算到GSM多部分长度

的UCS-2 16位字符的数量)。

*注意事项,一个关于计数字节的词:

  • Do而不是使用strlen来计数字节数。虽然它可以工作,但在具有多字节功能版本的PHP安装中,strlen经常被重载,并且也是future
  • Avoid mb_strlen($str, 'UCS-2').中API更改的候选。虽然它目前工作,并将正确地返回2的一堆粪便字符(因为它看起来像两个16位的UCS-2字符),其稳定的mb_convert_encoding是有损的,从>16位转换为UCS-2。谁能说future?
  • Avoid mb_strlen($str, '8bit') / 2.中的mb_strlen不会有损失?它目前也能工作,并在PHP文档注释中推荐作为计算字节的方法。但是,与上面的UCS-2 technique.
  • That一样,IMO也面临着同样的问题,即将当前最安全的方式(IMO)放入字节数组中,并对其进行计数。

这看起来像什么?

代码语言:javascript
复制
// 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;
}

把这一切结合在一起:

代码语言:javascript
复制
function multipart_count($str)
{
    $one_part_limit = 160; // use a constant i.e. GSM::SMS_SINGLE_7BIT
    $multi_limit = 153; // again, use a constant
    $max_parts = 3; // ... constant

    $str_length = count_gsm_string($str);
    if($str_length === -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

票数 8
EN

Stack Overflow用户

发布于 2020-07-02 13:45:30

  • 页面1: 160字节
  • 页2: 146字节
  • 页3: 153字节
  • 页4: 153字节
  • 页5: 153字节……H 210F 211

因此,不管语言如何:

代码语言:javascript
复制
// strlen($text) show bytes 

           $count = 0;
           $len = strlen($text);
                if ($len > 306) {
                    $len = $len - 306;
                    $count = floor($len / 153) + 3;
                } else if($len>160){
                    $count = 2;
                }else{
                    $count = 1;
                }
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8349831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档