码农老张Zy 潜水
  • 11发帖数
  • 11主题数
  • 0关注数
  • 0粉丝
开启左侧

简单入门PHP中的多字节字符串操纵

[复制链接]
码农老张Zy 发表于 2021-8-17 09:05:39 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
什么是多字节的字符串操纵呢?其实不少的同学可能都已经使用过了,但我们还是要从最基础的问题说起。
一个字符占几个字节并不是我们表面上看到的那样。正常环境下,一个数字或英文以及英文符号都是占用一个字节的。但是这个世界的语言笔墨何其之多,特别是像中文、日文如许的笔墨,往往用一个字节装不下,这时候就需要多字节来解决了(多字节一般第一个字节是前导字节表示当前是什么语言笔墨,反面的是正被的字节编码)。好比说一个中笔墨在 GBK 环境是占用两个字节,而在 UTF-8 下则是占用三个字节。而在最近几年,由于 emoji 表情的出现 UTF-8MB4 又成为了主流,在表示这些 emoji 表情字符的时候,往往又会使用 UTF-8MB4 这种占用四个字节的编码格式来表示。
虽说字节的差别设置能够帮助我们展示丰富的内容,但对它的一些操纵却也带来了麻烦。
字符串操纵

$str = "abc测试一下";echo strlen($str), PHP_EOL; // 15strlen() 函数各人都不陌生,但是对于中文来说,它返回的数目显着是不对的。我们当前默认的编码格式是 UTF-8 ,所以将一个中文当做三个英笔墨符来数就恰好是 15 个字符长度。很显着,这不是我们想要的结果,假设我们要截取字符串的话,这个长度的计算可是很费劲的,搞欠好还容易出现乱码。
幸好在 PHP 的默认扩展中就已经为我们准备好了一组 mb_ 函数库,专门用来处置处罚这类多字节字符串的问题。
echo mb_strlen($str), PHP_EOL; // 7echo mb_strlen($str, 'GB2312'), PHP_EOL; // 11在不指定 mb_strlen() 函数的第二个参数的环境下,会按照当前文档的默认编码格式来举行转换,所以我们的字符串长度就在 UTF-8 的环境下正常显示了。当然,我们也可以指定第二个参数为其它的编码格式,好比以前常用的 GB2312 或者 GBK ,如许返回的字符长度就是以一个中文占两个字节的形式返回长度了。
var_dump(mb_strpos($str, "测")); // int(3)var_dump(mb_convert_case($str, MB_CASE_UPPER)); // string(15) "ABC测试一下"var_dump(mb_convert_case($str, MB_CASE_LOWER)); // string(15) "abc测试一下"var_dump(mb_substr($str, 5)); // string(6) "一下"当然,mb_ 相干的字符串操纵函数是比力全面的,字符出现位置、大小写转换、截取字符串等函数都是提供的,调用的参数也都和普通的字符串操纵函数没什么区别,只是它们多了一个可选的指定编码的参数。在通常的环境下,只要我们的文件是对应的编码格式,这个参数就不消去写了。
当然,字符串的操纵函数还有很多,这里就不逐一列举了,各人可以自行查阅相干的文档。
字符串正则操纵

既然说到了字符串的操纵,正则相干的功能也是必不可少的,我们先看下使用默认的 preg_ 相干的函数操纵中文的问题。
$str = iconv('UTF-8', 'GB2312', $str);var_dump(preg_match("/[a-z]*测试/i", $str)); // int(0)var_dump(preg_replace("/[a-z]*测试/i","试试", $str)); // string(11) "abc"首先我们将测试用的字符串转换为 GB2312 的形式。就像我们获取的外部接口可能返回的就是 GB2312 的编码的。这时直接使用 preg_ 相干的函数是无法正确获得我们想要的结果的。
mb_regex_encoding('GB2312');$pattern = iconv('UTF-8', 'GB2312', "[a-z]*测试");var_dump(mb_ereg($pattern, $str)); // int(1)var_dump(mb_eregi($pattern, $str)); // int(1)var_dump(mb_ereg_replace($pattern,"试试", $str)); // string(10) "试试"var_dump(mb_eregi_replace($pattern,"试试", $str)); // string(10) "试试"接下来我们通过 mb_ereg 相干的函数来举行正则的匹配和更换,就能正常的对差别编码的字符串举行操纵了。注意,我们需要指定 mb_regex_encoding() 函数,告诉当前默认的规划更换编码是 GB2312 ,同时,正则规则也要转换成对应的编码格式。
mb_eregi 相干的函数和 mb_ereg 其实没有本质上的区别,只是它不区分大小写了,就像 preg 相干函数中我们写正则时的后缀符号 i 一样。ereg 相干的函数都是不消写反斜杠的,在普通的函数中其实是已经被镌汰了的函数(性能没有 preg 好,语法也有区别),大部门环境下都会直接使用 preg 相干的函数来举行操纵。不过如果是牵涉到多字节相干的问题,在 mb_ 函数库中还是只有 ereg 这类的函数可以使用。
字符串编码转换

就像我们之前学习过的 iconv() 函数一样,mb_ 库中也提供了字符编码转换的函数。
$phone = file_get_contents('https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13888888888');print_r($phone);// __GetZoneResult_ = {//     mts:'1388888',//     province:'',//     catName:'й',//     telString:'13888888888',//     areaVid:'30515',//     ispVid:'3236139',//     carrier:''// }var_dump(mb_convert_encoding($phone, 'UTF-8', "GBK"));// string(183) "__GetZoneResult_ = {//     mts:'1388888',//     province:'云南',//     catName:'中国移动',//     telString:'13888888888',//     areaVid:'30515',//     ispVid:'3236139',//     carrier:'云南移动'// }// "echo mb_detect_encoding($phone, 'UTF-8,GBK'), PHP_EOL; // CP936同样我们还是拿这个获取手机号信息的公共接口测试,它返回的内容是 GBK 的编码内容。我们可以通过 mb_convert_encoding() 来转换它的编码内容。mb_detect_encoding() 是检测编码格式,这里我们给了两个参数,它会返回符合条件的编码内容,CP936 就是 GBK 的另一种表示(IBM在制作 code page 时将 GBK 编码放在了第 936 页)。
HTTP 参数操纵

mb_internal_encoding("UTF-8");首先介绍一个 mb_internal_encoding() 函数,其实就是设置当前运行环境中的默认编码规则的,如果不设置的话,就是以当前这个 php 文件的编码规则为默认的。各人了解一下,因为它会影响我们反面介绍的内容。
// // localhost:9991/?a=我上var_dump(mb_http_input('GPC')); // bool(false)var_dump(mb_http_output()); // string(5) "UTF-8"mb_internal_encoding("CP936");mb_parse_str($_SERVER['QUERY_STRING'], $result);print_r($result);// Array// (//     [a] => 我上// )首先我们运行起来测试文件,然后用浏览器哀求这个链接地点。mb_http_input() 是检测 HTTP 输入字符编码,不过我测试的结果都是返回 false 。有了解的小伙伴可以留言说明下这个是什么环境。而 mb_http_output 则是设置检测输出的编码,这个就会受到 mb_internal_encoding() 所定义的内容的影响。
另外,mb_parse_str() 是 parse_str() 函数的多字节版,我们可以将浏览器的默认编码转换成 GBK 或者 之后再来哀求,因为我们设置当前的 mb_internal_encoding() 为 CP936 了。在默认环境下,如果使用 UTF-8 的浏览器哀求的话,这里就会报错了,这就是 mb_internal_encoding() 对这些函数的影响。
其它属性查察

最后,我们再来看看一些 mb_ 相干信息属性的内容。
var_dump(mb_language());// string(7) "neutral"mb_language() 函数用于获取/设置当前的语言,它可以接收一个参数设置当前的语言信息。主要用于编码邮件信息 mb_send_mail() 函数就是使用它来对邮件举行编码。关于 mb_send_mail() 的使用各人可以自己实验一下,其实也是 send_mail() 函数的多字节版。neutral 的意思是中立的,其实也是跟我们的 mb_internal_encoding() 有关。
var_dump(mb_list_encodings());// array(86) {//     [0]=>//     string(4) "pass"//     [1]=>//     string(5) "wchar"//     [2]=>//     string(7) "byte2be"//     [3]=>//     ……//     [65]=>//     string(5) "CP936"//     ……mb_list_encodings() 用于展示当前系统中所支持的所有语言编码的列表,在这个列表中我们就可以看到 CP936 的身影,但是没有 GBK 哦,记取它们俩是一个东西就好了。
var_dump(mb_get_info());// array(14) {//     ["internal_encoding"]=>//     string(5) "UTF-8"//     ["http_output"]=>//     string(5) "UTF-8"//     ["http_output_conv_mimetypes"]=>//     string(31) "^(text/|application/xhtml\+xml)"//     ["func_overload"]=>//     int(0)//     ["func_overload_list"]=>//     string(11) "no overload"//     ["mail_charset"]=>//     string(5) "UTF-8"//     ["mail_header_encoding"]=>//     string(6) "BASE64"//     ["mail_body_encoding"]=>//     string(6) "BASE64"//     ["illegal_chars"]=>//     int(0)//     ["encoding_translation"]=>//     string(3) "Off"//     ["language"]=>//     string(7) "neutral"//     ["detect_order"]=>//     array(2) {//       [0]=>//       string(5) "ASCII"//       [1]=>//       string(5) "UTF-8"//     }//     ["substitute_character"]=>//     int(63)//     ["strict_detection"]=>//     string(3) "Off"//   }mb_get_info() 是查察当前环境下默认的这些语言编码的配置,好比我们熟悉的 internal_encoding 、 http_output 属性都能在这里看到。
总结

用过的同学是不是也发现了今天文章的新姿势了呢?没错,GBK 和 CP936 反而成为了今天文章的意外惊喜。这个在之前确实还真没有注意到。其实 mb_ 相干的函数的使用已经非常广泛了,基本算是学习 PHP 的入门必备知识了。它还有很多的函数并没有逐一地列举出来,有爱好的同学可以多多查阅官方手册举行更加深入地学习。
测试代码:
[https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/10.简朴入门PHP中的多字节字符串操纵.php][https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/10.简朴入门PHP中的多字节字符串操纵.php]
参考文档:
https://www.php.net/manual/zh/book.mbstring.php
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

猜你喜欢
在线客服QQ
2241998733

24x7小时免费咨询

Powered by 创意电子 ©2018-现在 专注资源实战分享源码下载站联盟商城繁体中文