PHP中多字节字符串操作实例详解

目录
  • 前言
  • 字符串操作
  • 字符串正则操作
  • 字符串编码转换
  • HTTP 参数操作
  • 其它属性查看
  • 总结

前言

什么是多字节的字符串操作呢?其实不少的同学可能都已经使用过了,但我们还是要从最基础的问题说起。

一个字符占几个字节并不是我们表面上看到的那样。正常情况下,一个数字或英文以及英文符号都是占用一个字节的。但是这个世界的语言文字何其之多,特别是像中文、日文这样的文字,往往用一个字节装不下,这时候就需要多字节来解决了(多字节一般第一个字节是前导字节表示当前是什么语言文字,后面的是正被的字节编码)。比如说一个中文字在 GBK 环境是占用两个字节,而在 UTF-8 下则是占用三个字节。而在最近几年,由于 emoji 表情的出现 UTF-8MB4 又成为了主流,在表示这些 emoji 表情字符的时候,往往又会使用 UTF-8MB4 这种占用四个字节的编码格式来表示。

虽说字节的不同设置能够帮助我们展示丰富的内容,但对它的一些操作却也带来了麻烦。

字符串操作

$str = "abc测试一下";
echo strlen($str), PHP_EOL; // 15

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

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

echo mb_strlen($str), PHP_EOL; // 7
echo 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 的入门必备知识了。它还有很多的函数并没有一一地列举出来,有兴趣的同学可以多多查阅官方手册进行更加深入地学习。

测试代码:

[github.com/zhangyue050…]

参考文档:

www.php.net/manual/zh/b

到此这篇关于PHP中多字节字符串操作的文章就介绍到这了,更多相关PHP多字节字符串操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PHP开发中常用的字符串操作函数

    1,拼接字符串 拼接字符串是最常用到的字符串操作之一,在PHP中支持三种方式对字符串进行拼接操作,分别是圆点.分隔符{}操作,还有圆点等号.=来进行操作,圆点等号可以把一个比较长的字符串分解为几行进行定义,这样做是比较有好处的. 2,替换字符串 在PHP这门语言中,提供了一个名字叫做substr_replace()的函数,该函数的作用可以快速的完成扫描和编辑文本内容较多的字符串替换功能.他的语法格式: mixed substr_replace(mixed $string,string $repl

  • PHP常见字符串操作函数与用法总结

    本文实例讲述了PHP常见字符串操作函数与用法.分享给大家供大家参考,具体如下: 一.字符串的格式化 1.字符串的格式化 trim()函数可以去除字符串的开始位置和结束位置的空格,并将结果字符串返回,默认情况下去除的字符是换行符和回车符(\n和\r),水平和垂直制表符(\t和X0B) ltrim()函数只从字符的开始处(左边)去除空格 rtrim()函数只从函数的结束处(右边)去除空格 2.格式化字符串以便显示 ①使用HTML格式化:n12br()函数 在字符串中的新行(\n)之前插入换行符 <?

  • PHP 字符串操作入门教程

    无论哪种语言,字符串操作都是一个重要的基础,往往是简单而重要.正像人说话一样,一般有形体(图形界面),有语言(print 字符串?),显然字符串能解释更多的东西.PHP提供了大量的字符串操作函数,功能强大,使用也比较简单,详细请参看 http://cn2.php.net/manual/zh/ref.strings.php . 以下将简单的讲述它的功能和特性. 弱类型 PHP是弱类型语言,所以其它类型的数据一般可以直接应用于字符串操作函数里,而自动转换成字符串类型,进行处理,如: echo sub

  • php字符串操作针对负值的判断分析

    本文实例分析了php字符串操作针对负值的判断方法.分享给大家供大家参考,具体如下: $a = '-1'; $b = (int)$a; $c = is_numeric($a); if ($a) { echo 1; //echo 1 } else { echo 2; } var_dump($b); // int(-1) var_dump($c); // true 运行结果输出如下: 1 int -1 boolean true 总结: 字符串 '-1'的逻辑值是true; 更多关于PHP相关内容感兴趣

  • php简单实现多字节字符串翻转的方法

    本文实例讲述了php简单实现多字节字符串翻转的方法.分享给大家供大家参考.具体实现方法如下: <?php function mb_strev ($string, $encoding = null) { if ($encoding === null) { $encoding = mb_detect_encoding($string); } $length = mb_strlen($string, $encoding); $reversed = ''; while($length-- > 0) {

  • PHP中多字节字符串操作实例详解

    目录 前言 字符串操作 字符串正则操作 字符串编码转换 HTTP 参数操作 其它属性查看 总结 前言 什么是多字节的字符串操作呢?其实不少的同学可能都已经使用过了,但我们还是要从最基础的问题说起. 一个字符占几个字节并不是我们表面上看到的那样.正常情况下,一个数字或英文以及英文符号都是占用一个字节的.但是这个世界的语言文字何其之多,特别是像中文.日文这样的文字,往往用一个字节装不下,这时候就需要多字节来解决了(多字节一般第一个字节是前导字节表示当前是什么语言文字,后面的是正被的字节编码).比如说

  • JDBC中resutset接口操作实例详解

    本文主要向大家展示JDBC接口中resutset接口的用法实例,下面我们看看具体内容. 1. ResultSet细节1 功能:封锁结果集数据 操作:如何获得(取出)结果 package com.sjx.a; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; //1. next方

  • python中list常用操作实例详解

    本文实例讲述了python中list常用操作.分享给大家供大家参考.具体分析如下: 1.定义list >>> li = ["a", "b", "mpilgrim", "z", "example"] >>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li[0] 'a' >>> li[4]

  • PHP弱类型语言中类型判断操作实例详解

    本文实例讲述了PHP弱类型语言中类型判断操作.分享给大家供大家参考,具体如下: 1.php一个数字和一个字符串进行比较或者进行运算时,PHP会把字符串转换成数字再进行比较.PHP转换的规则的是:若字符串以数字开头,则取开头数字作为转换结果,若无则输出0. 例如:123abc转换后应该是123,而abc则为0,0==0这当然是成立的.具体可以参考官方手册:如果比较一个整数和字符串,则字符串会被转换为整数 $a = ($b=4)+5; echo $a; //9 echo '<p>'; var_du

  • php 中的信号处理操作实例详解

    本文实例讲述了php 中的信号处理操作.分享给大家供大家参考,具体如下: 首先我们需要了解几个函数 pcntl_signal   安装信号处理器,也就是当指定信号发生时,调用函数. pcntl_alarm   指定秒数后向进程发送SIGALRM信号. posix_getpid 返回当前进程id posix_kill       给指定进程发送信号 一些常用的信号说明 SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业

  • Java中Properties类的操作实例详解

    Java中Properties类的操作实例详解 知识学而不用,就等于没用,到真正用到的时候还得重新再学.最近在看几款开源模拟器的源码,里面涉及到了很多关于Properties类的引用,由于Java已经好久没用了,而这些模拟器大多用Java来写,外加一些脚本语言Python,Perl之类的,不得已,又得重新拾起.本文通过看<Java编程思想>和一些网友的博客总结而来,只为简单介绍Properties类的相关操作.  一.Java Properties类 Java中有个比较重要的类Properti

  • Mybatis中的resultType和resultMap查询操作实例详解

    resultType和resultMap只能有一个成立,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,resultMap解决复杂查询是的映射问题.比如:列名和对象属性名不一致时可以使用resultMap来配置:还有查询的对象中包含其他的对象等. MyBatisConfig.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configura

  • C++ 中String 替换指定字符串的实例详解

    C++ 中String 替换指定字符串的实例详解 C++的string提供了replace方法来实现字符串的替换,但是对于将字符串中某个字符串全部替换这个功能,string并没有实现,我们今天来做的就是这件事. 首先明白一个概念,即string替换所有字符串,将"12212"这个字符串的所有"12"都替换成"21",结果是什么? 可以是22211,也可以是21221,有时候应用的场景不同,就会希望得到不同的结果,所以这两种答案都做了实现, 代码如

  • Laravel框架中队列和工作(Queues、Jobs)操作实例详解

    在我们的web应用中,经常会遇到这样的情况: 用户在进行了某项操作后,我们需要在后台完成一个耗时且耗费资源的任务,以对应用户的操作. 通常来说,web应用中的操作都是同步的(synchronous),即用户的操作可以立即得到回馈. 但是在以上情况下,同步等待操作结果将是灾难性的.比如用户点击了申请密码重置邮件,倘若我们让用户一直停滞在等待页面,直至邮件发送成功,那么用户体验将非常地不好,因为有时候可能需要很长的时间才能将邮件发送完成. 从另一个角度来说,如果我们服务器处于高负荷的情况,当多个用户

  • Python字符串处理实例详解

    Python字符串处理实例详解 一.拆分含有多种分隔符的字符串 1.如何拆分含有多种分隔符的字符串 问题: 我们要把某个字符串依据分隔符号拆分不同的字段,该字符串包含多种不同的分隔符,例如: s = "ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz" 其中;,|,\t 都是分隔符号,如何处理? 方法一: 连续使用str.split()方法,每次处理一种分隔符号 s = "ab;cd|efg|hi,jkl|mn\topq;rst,uvw\txyz&q

随机推荐