请选择 进入手机版 | 继续访问电脑版

[PHP编程] PHP中多字节字符串操作实例详解

  [复制链接]
查看214 | 回复68 | 2021-9-13 06:57:29 | 显示全部楼层 |阅读模式
目次

媒介

什么是多字节的字符串操作呢?实在 不少的同砚 大概 都已经利用 过了,但我们还是要从最基础的题目 提及 。

一个字符占几个字节并不是我们表面上看到的那样。正常环境 下,一个数字或英文以及英文符号都是占用一个字节的。但是这个天下 的语言笔墨 何其之多,特殊 是像中文、日文如许 的笔墨 ,每每 用一个字节装不下,这时间 就必要 多字节来办理 了(多字节一样平常 第一个字节是前导字节表示当前是什么语言笔墨 ,后面的是正被的字节编码)。比如说一个中笔墨 在 GBK 环境是占用两个字节,而在 UTF-8 下则是占用三个字节。而在迩来 几年,由于 emoji 表情的出现 UTF-8MB4 又成为了主流,在表示这些 emoji 表情字符的时间 ,每每 又会利用 UTF-8MB4 这种占用四个字节的编码格式来表示。

虽说字节的不同设置可以或许 帮助我们展示丰富的内容,但对它的一些操作却也带来了贫苦 。

字符串操作

  1. $str = "abc测试一下";
  2. echo strlen($str), PHP_EOL; // 15
复制代码

strlen() 函数大家都不生疏 ,但是对于中文来说,它返回的数目 显着 是不对的。我们当前默认的编码格式是 UTF-8 ,以是 将一个中文当做三个英笔墨 符来数就恰好 是 15 个字符长度。很显着 ,这不是我们想要的效果 ,假设我们要截取字符串的话,这个长度的计算但是 很费劲的,搞不好还容易 出现乱码。

幸好在 PHP 的默认扩展中就已经为我们预备 好了一组 mb_ 函数库,专门用来处理这类多字节字符串的题目 。

  1. echo mb_strlen($str), PHP_EOL; // 7
  2. echo mb_strlen($str, 'GB2312'), PHP_EOL; // 11
复制代码

在不指定 mb_strlen() 函数的第二个参数的环境 下,会按照当前文档的默认编码格式来举行 转换,以是 我们的字符串长度就在 UTF-8 的环境下正常表现 了。当然,我们也可以指定第二个参数为别的 的编码格式,比如从前 常用的 GB2312 或者 GBK ,如许 返回的字符长度就是以一个中文占两个字节的情势 返回长度了。

  1. var_dump(mb_strpos($str, "测")); // int(3)
  2. var_dump(mb_convert_case($str, MB_CASE_UPPER)); // string(15) "ABC测试一下"
  3. var_dump(mb_convert_case($str, MB_CASE_LOWER)); // string(15) "abc测试一下"
  4. var_dump(mb_substr($str, 5)); // string(6) "一下"
复制代码

当然,mb_ 干系 的字符串操作函数是比较全面的,字符出现位置、大小写转换、截取字符串等函数都是提供的,调用的参数也都和平常 的字符串操作函数没什么区别,只是它们多了一个可选的指定编码的参数。在通常的环境 下,只要我们的文件是对应的编码格式,这个参数就不用去写了。

当然,字符串的操作函数还有很多,这里就不逐一 枚举 了,大家可以自行查阅干系 的文档。

字符串正则操作

既然说到了字符串的操作,正则干系 的功能也是必不可少的,我们先看下利用 默认的 preg_ 干系 的函数操作中文的题目 。

  1. $str = iconv('UTF-8', 'GB2312', $str);
  2. var_dump(preg_match("/[a-z]*测试/i", $str)); // int(0)
  3. var_dump(preg_replace("/[a-z]*测试/i","试试", $str)); // string(11) "abc����һ��"
复制代码

起首 我们将测试用的字符串转换为 GB2312 的情势 。就像我们获取的外部接口大概 返回的就是 GB2312 的编码的。这时直接利用 preg_ 干系 的函数是无法准确 获得我们想要的效果 的。

  1. mb_regex_encoding('GB2312');
  2. $pattern = iconv('UTF-8', 'GB2312', "[a-z]*测试");
  3. var_dump(mb_ereg($pattern, $str)); // int(1)
  4. var_dump(mb_eregi($pattern, $str)); // int(1)
  5. var_dump(mb_ereg_replace($pattern,"试试", $str)); // string(10) "试试һ��"
  6. 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_ 库中也提供了字符编码转换的函数。

  1. $phone = file_get_contents('https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13888888888');
  2. print_r($phone);
  3. // __GetZoneResult_ = {
  4. // mts:'1388888',
  5. // province:'����',
  6. // catName:'�й��ƶ�',
  7. // telString:'13888888888',
  8. // areaVid:'30515',
  9. // ispVid:'3236139',
  10. // carrier:'�����ƶ�'
  11. // }
  12. var_dump(mb_convert_encoding($phone, 'UTF-8', "GBK"));
  13. // string(183) "__GetZoneResult_ = {
  14. // mts:'1388888',
  15. // province:'云南',
  16. // catName:'中国移动',
  17. // telString:'13888888888',
  18. // areaVid:'30515',
  19. // ispVid:'3236139',
  20. // carrier:'云南移动'
  21. // }
  22. // "
  23. 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 参数操作

  1. mb_internal_encoding("UTF-8");
复制代码

起首 先容 一个 mb_internal_encoding() 函数,实在 就是设置当前运行环境中的默认编码规则的,假如 不设置的话,就是以当前这个 php 文件的编码规则为默认的。大家相识 一下,由于 它会影响我们后面先容 的内容。

  1. // // localhost:9991/?a=我上
  2. var_dump(mb_http_input('GPC')); // bool(false)
  3. var_dump(mb_http_output()); // string(5) "UTF-8"
  4. mb_internal_encoding("CP936");
  5. mb_parse_str($_SERVER['QUERY_STRING'], $result);
  6. print_r($result);
  7. // Array
  8. // (
  9. // [a] => 我上
  10. // )
复制代码

起首 我们运行起来测试文件,然后用欣赏 器哀求 这个链接地址。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_ 干系 信息属性的内容。

  1. var_dump(mb_language());
  2. // string(7) "neutral"
复制代码

mb_language() 函数用于获取/设置当前的语言,它可以吸收 一个参数设置当前的语言信息。重要 用于编码邮件信息  mb_send_mail() 函数就是利用 它来对邮件举行 编码。关于  mb_send_mail() 的利用 大家可以本身 尝试一下,实在 也是 send_mail() 函数的多字节版。neutral 的意思是中立的,实在 也是跟我们的 mb_internal_encoding() 有关。

  1. var_dump(mb_list_encodings());
  2. // array(86) {
  3. // [0]=>
  4. // string(4) "pass"
  5. // [1]=>
  6. // string(5) "wchar"
  7. // [2]=>
  8. // string(7) "byte2be"
  9. // [3]=>
  10. // ……
  11. // [65]=>
  12. // string(5) "CP936"
  13. // ……
复制代码

mb_list_encodings() 用于展示当前体系 中所支持的全部 语言编码的列表,在这个列表中我们就可以看到 CP936 的身影,但是没有 GBK 哦,记住它们俩是一个东西就好了。

  1. var_dump(mb_get_info());
  2. // array(14) {
  3. // ["internal_encoding"]=>
  4. // string(5) "UTF-8"
  5. // ["http_output"]=>
  6. // string(5) "UTF-8"
  7. // ["http_output_conv_mimetypes"]=>
  8. // string(31) "^(text/|application/xhtml\+xml)"
  9. // ["func_overload"]=>
  10. // int(0)
  11. // ["func_overload_list"]=>
  12. // string(11) "no overload"
  13. // ["mail_charset"]=>
  14. // string(5) "UTF-8"
  15. // ["mail_header_encoding"]=>
  16. // string(6) "BASE64"
  17. // ["mail_body_encoding"]=>
  18. // string(6) "BASE64"
  19. // ["illegal_chars"]=>
  20. // int(0)
  21. // ["encoding_translation"]=>
  22. // string(3) "Off"
  23. // ["language"]=>
  24. // string(7) "neutral"
  25. // ["detect_order"]=>
  26. // array(2) {
  27. // [0]=>
  28. // string(5) "ASCII"
  29. // [1]=>
  30. // string(5) "UTF-8"
  31. // }
  32. // ["substitute_character"]=>
  33. // int(63)
  34. // ["strict_detection"]=>
  35. // string(3) "Off"
  36. // }
复制代码

mb_get_info() 是查看当前环境下默认的这些语言编码的设置 ,比如我们熟悉 的 internal_encoding 、 http_output 属性都能在这里看到。

总结

用过的同砚 是不是也发现了本日 文章的新姿势了呢?没错,GBK 和 CP936 反而成为了本日 文章的不测 惊喜。这个在之前确实还真没有留意 到。实在 mb_ 干系 的函数的利用 已经非常广泛 了,基本算是学习 PHP 的入门必备知识了。它还有很多的函数并没有逐一 地枚举 出来,有爱好 的同砚 可以多多查阅官方手册举行 更加深入地学习。

测试代码:

[github.com/zhangyue050…]

参考文档:

www.php.net/manual/zh/b

到此这篇关于PHP中多字节字符串操作的文章就先容 到这了,更多干系 PHP多字节字符串操作内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章渴望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 待该州伙 | 2021-9-13 08:57:05 | 显示全部楼层
我只看看不说话。。。
回复

使用道具 举报

avatar 厕所有人 | 2021-9-13 12:22:01 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的源码论坛他的站点都是商业源码,还是免费下载的那种!特别好用。访问地址:http://www.mxswl.com 猫先森网络
回复

使用道具 举报

avatar 哈哈小强呀 | 2021-9-15 15:38:42 | 显示全部楼层
今天的心情很不错啊
回复

使用道具 举报

avatar 小雨粑粑2012 | 2021-9-15 21:41:56 | 显示全部楼层
今天过得很不爽!
回复

使用道具 举报

avatar 123457732 | 2021-9-15 22:20:09 | 显示全部楼层
看帖不回帖都是耍流氓!
回复

使用道具 举报

avatar 礼记离 | 2021-9-17 10:59:08 | 显示全部楼层
论坛的帖子越来越有深度了!
回复

使用道具 举报

avatar wxf2017 | 2021-9-17 19:07:31 | 显示全部楼层
不错哦,admin楼主这是要火的节奏啊!
回复

使用道具 举报

avatar 红军利物浦2017 | 2021-9-20 08:48:24 | 显示全部楼层
admin楼主给脑残下了定义!
回复

使用道具 举报

avatar 尹泽汐猩 | 2021-9-29 10:22:07 | 显示全部楼层
我只是来赚积分的!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则