想必 iconv 这个扩大的相干函数大家多少都接触过,做为 PHP 的默认扩大它曾经存在了很久,也是咱们在操作字符编码时常常会应用的函数。不过除了 iconv() 这个函数外,你还晓得它的其它函数吗?明天,咱们就来学习一下 iconv 扩大中的各种好玩的函数。
iconv 设置及获取信息
首先,就是咱们能够设置 iconv 扩大中默认定义的输入和输入字符编码格局。
<code class="php">iconv_set_encoding("internal_encoding", "UTF-8"); // Deprecated: iconv_set_encoding(): Use of iconv.internal_encoding is deprecated iconv_set_encoding("output_encoding", "ISO-8859-1"); // Deprecated: iconv_set_encoding(): Use of iconv.output_encoding is deprecated var_dump(iconv_get_encoding()); // array(3) { // ["input_encoding"]=> // string(5) "UTF-8" // ["output_encoding"]=> // string(10) "ISO-8859-1" // ["internal_encoding"]=> // string(5) "UTF-8" // }
iconv_set_encoding() 接管两个参数,一个是设置的属性类型,一个是设置的编码格局。属性类型包含 internal_encoding 、 input_encoding 和 output_encoding ,别离代表外部的、输出的、输入的编码格局。在这段测试代码中,咱们将 internal_encoding 设置为 UTF8 ,将 output_encoding 设置为 ISO-8859-1 ,而后应用 iconv_get_encoding() 打印出以后环境中相干的 iconv 属性设置信息,能够看到,在默认状况下以后环境中的 input_encoding 也是 UTF8 格局。
不过须要阐明的是,iconv_set_encoding() 曾经是不举荐应用的函数了,或者说不举荐应用这个函数来设置下面的三种属性类型,它们会报出过期正告信息。当初更举荐间接应用 php.ini 中的 default_charset 来进行设置。
iconv 依据编码获取字符长度、指定地位及截取字符串
在面对中文字符串的操作时,咱们应用默认的 strlen() 之类的函数返回的中文字符长度是不正确的,这就牵涉到编码的问题。个别状况下,UTF8 是占三个字节,而 GBK 是占两个字节,所以说一个汉字对于 strlen() 来说如果是在 UTF8 环境中会返回 3 。当然,当初大多数状况下咱们会应用 MB 库扩大的相干函数来解决这种问题,不过 iconv 也为咱们提供了几个用于字符串操作的函数。
<code class="php">echo iconv_strlen("测试长度测试长度"), PHP_EOL; // 8 echo iconv_strlen("测试长度测试长度", 'ISO-8859-1'), PHP_EOL; // 24 echo iconv_strlen("测试长度测试长度", 'GBK'), PHP_EOL; // 12 echo '======', PHP_EOL; echo iconv_strpos("测试长度测试长度", "长"), PHP_EOL; // 2 echo iconv_strpos("测试长度测试长度", "长", 0, 'ISO-8859-1'), PHP_EOL; // 6 echo iconv_strpos("测试长度测试长度", "长", 0, 'GBK'), PHP_EOL; // echo '======', PHP_EOL; echo iconv_strrpos("测试长度测试长度", "长"), PHP_EOL; // 6 echo iconv_strrpos("测试长度测试长度", "长", 'ISO-8859-1'), PHP_EOL; // 18 echo '======', PHP_EOL; echo iconv_substr("测试长度测试长度", 2, 4), PHP_EOL; // 长度测试 echo iconv_substr("测试长度测试长度", 6, 12, 'ISO-8859-1'), PHP_EOL; // 长度测试 echo iconv_substr("测试长度测试长度", 3, 6, 'GBK'), PHP_EOL; // 长度测试
iconv_strlen() 就是获取字符串长度的,如果不给第二个参数就按默认的字符集编码来获取字符串长度。在测试代码中能够看出,同样八个中文字的内容,应用不同的编码返回的数量是不雷同的。在这里,咱们发现 iconv 中对于 GBK 的中文是 1.5 个字节,也就是 8 个中文字占用了 12 个字节的长度。
iconv_strpos() 和 iconv_strrpos() 和 strpos() 的作用一样,返回某个字符第一次呈现的地位,一个是从返回后(从左往右),另一个是从后往前(从右往左)。它们的第三个参数是偏移量,也就是查找到指定字符后再偏移几个单位。从这里咱们能够看出,对于 GBK 编码的操作是有问题的,因为在 iconv 中,GBK 是 1.5 个字节,这样会带来单个字符无奈定位的问题。
iconv_substr() 很显著地就是截取字符串的函数了,同样咱们要依据编码格局来指定它的截取地位。
iconv 转换字符编码
接下来就是本尊 iconv() 函数的应用的了,其实它反而没什么可讲的,将指定的编码转换成另外一种编码而已,置信这个函数大家都不生疏。
<code class="php">$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:'�����ƶ�' // } print_r(iconv('GBK', 'UTF-8', $phone)); // __GetZoneResult_ = { // mts:'1388888', // province:'云南', // catName:'中国移动', // telString:'13888888888', // areaVid:'30515', // ispVid:'3236139', // carrier:'云南挪动' // } print_r(iconv('GBK', 'ISO-8859-1//IGNORE', $phone)); // __GetZoneResult_ = { // mts:'1388888', // province:'', // catName:'', // telString:'13888888888', // areaVid:'30515', // ispVid:'3236139', // carrier:'' // }
咱们找到的这个淘宝用于查找手机号相干信息的凋谢接口,返回的正好是 GBK 类型的数据。当咱们间接打印后果时,在 UTF8 环境下它就会输入乱码信息。这时,咱们通过 iconv() 函数就可能轻松地将编码转换成 UTF8 格局,并正确打印出了后果。第三个测试中,咱们在要转换到的字符集编码类型前面加上了 //IGNORE ,目标就是疏忽无奈转换的内容,所以能够看出在最初咱们转换到谬误的 ISO-8859-1 时,中文信息就全都没有了,因为它们无奈转换就被疏忽掉了。
mime 邮件头操作
最初咱们再看一个十分不罕用的内容,那就是 iconv 还能够间接转换 mime 头中的编码内容信息。这个 mime 头信息其实就是标示以后文件或者内容的 mime 类型。平时咱们会依据它来判断上传的文件是否正确,除些之外,在邮件发送中,这个 mime 头的应用也十分宽泛。如果做过邮件发送接管相干的开发并且抓过包的同学肯定见过上面的内容。
<code class="php">headers_string = <<<EOF Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?= To: [email protected] Date: Thu, 1 Jan 1970 00:00:00 +0000 Message-Id: <[email protected]> Received: from localhost (localhost [127.0.0.1]) by localhost with SMTP id example for <[email protected]>; Thu, 1 Jan 1970 00:00:00 +0000 (UTC) (envelope-from [email protected]) Received: (qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000 EOF;
Subject 字符就是邮件的题目,To 就是发送人的邮件地址。在这里咱们次要看一下 Subject 的内容,它的结尾就有一段形容这个字段应用的编码信息的内容,?UTF-8 ,而后前面是一堆看不懂的货色。其实咱们简略地能看进去这是一个 base64 编码的内容,如果将它解码在对应的编码内容下就能看到原文信息。不过,这个时候咱们也能够应用 iconv 来间接转换它的编码。
<code class="php">$headers = iconv_mime_decode_headers($headers_string, 0, "ISO-8859-1"); var_dump($headers); // array(5) { // ["Subject"]=> // string(15) "Pr�fung Pr�fung" // ["To"]=> // string(19) "[email protected]" // ["Date"]=> // string(30) "Thu, 1 Jan 1970 00:00:00 +0000" // ["Message-Id"]=> // string(21) "<[email protected]>" // ["Received"]=> // array(2) { // [0]=> // string(204) "from localhost (localhost [127.0.0.1]) by localhost with SMTP id example for <[email protected]>; Thu, 1 Jan 1970 00:00:00 +0000 (UTC) (envelope-from [email protected])" // [1]=> // string(57) "(qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000" // } // }
看到了么?不仅间接转了编码,而且还将 mime 头格局转换成了 PHP 中的数组格局。当然,咱们这里测试的代码是将失常的内容转换到 ISO-8859-1 了,反而是呈现了乱码。上面咱们再拿一个中文邮件的例子来看下。
<code class="php">$headers_string = <<<EOF Return-Path: <[email protected]> Delivered-To: [email protected] Received: (qmail 75513 invoked by alias); 20 May 2002 02:19:53 -0000 Received: from unknown (HELO bluesky) (61.155.118.135) by 202.106.187.143 with SMTP; 20 May 2002 02:19:53 -0000 Message-ID: <007f01c3111c$742fec00$0100007f@bluesky> From: "=?gb2312?B?wLbAtrXEzOwNCg==?=" <[email protected]> To: "bhw98" <[email protected]> Cc: <[email protected]> Subject: =?gb2312?B?ztK1xLbgtK6/2rPM0PI=?= Date: Sat, 20 May 2002 10:03:36 +0800 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_007A_01C3115F.80DFC5E0" EOF; $headers = iconv_mime_decode_headers($headers_string, 0, "UTF-8"); var_dump($headers); // array(11) { // ["Return-Path"]=> // string(21) "<[email protected]>" // ["Delivered-To"]=> // string(14) "[email protected]" // ["Received"]=> // array(2) { // [0]=> // string(58) "(qmail 75513 invoked by alias); 20 May 2002 02:19:53 -0000" // [1]=> // string(101) "from unknown (HELO bluesky) (61.155.118.135) by 202.106.187.143 with SMTP; 20 May 2002 02:19:53 -0000" // } // ["Message-ID"]=> // string(40) "<007f01c3111c$742fec00$0100007f@bluesky>" // ["From"]=> // string(38) ""蓝蓝的天 // " <[email protected]>" // ["To"]=> // string(24) ""bhw98" <[email protected]>" // ["Cc"]=> // string(21) "<[email protected]>" // ["Subject"]=> // string(21) "我的多串口程序" // ["Date"]=> // string(31) "Sat, 20 May 2002 10:03:36 +0800" // ["MIME-Version"]=> // string(3) "1.0" // ["Content-Type"]=> // string(16) "multipart/mixed;" // }
这个中文邮件 mime 头的 Subject 指定的是 GB2312 。通过 iconv_mime_decode_headers() 函数咱们将整个头信息中的内容都转换成了 UTF8 ,这时就能够失常显示所有的内容信息了。当然,咱们也能够对单个的 mime 字段进行转码。
<code class="php">echo iconv_mime_decode("Subject: =?gb2312?B?ztK1xLbgtK6/2rPM0PI=?=", 0, 'UTF-8'), PHP_EOL; // Subject: 我的多串口程序
除了对于接管的信息进行编码转换之外,咱们还能够本人编码相干的内容进行发送应用。
<code class="php">$preferences = array( "input-charset" => "UTF-8", "output-charset" => "GBK", "line-length" => 76, "line-break-chars" => "\n" ); $preferences["scheme"] = "Q"; echo iconv_mime_encode("Subject", "测试头", $preferences), PHP_EOL; // Subject: =?GBK?Q?=B2=E2=CA=D4=CD=B7?= $preferences["scheme"] = "B"; echo iconv_mime_encode("Subject", "测试头", $preferences), PHP_EOL; // Subject: =?GBK?B?suLK1M23?=
iconv_mime_encode() 函数就是用于进行 mime 头编码的函数。第一个参数是 mime 字段名,第二个参数是字段值,第三个函数就是咱们进行编码的参数了。编码参数的内容通过字段名就可以看进去,从什么编码转换成什么编码,行的长度多少,换行符是什么。另外它还有一个 scheme 字段,就是用于指定编码后果的类型,如果设置的是 B ,那么编码后果就会再加一层 base64 操作。
总结
是不是感觉奇怪的小姿态又减少了呀?没错,在没刷文档之前我也只晓得一个 iconv 而已。甚至在学习了这些内容之后我才发现了邮件信息原来是这样编码的,本人都感觉本人一下子高大上了。好了,不说废话了,本人入手试试吧!
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/2.学习PHP中的iconv扩大相干函数.php
参考文档:
https://www.cnblogs.com/onelikeone/p/7865596.html
https://www.php.net/manual/zh/book.iconv.php
各自媒体平台均可搜寻【硬核项目经理】