iconv_set_encoding(34;internal_encoding", "UTF-8");// Deprecated: iconv_set_encoding(): Use of iconv.internal_encoding is deprecatediconv_set_encoding("output_encoding", "ISO-8859-1");// Deprecated: iconv_set_encoding(): Use of iconv.output_encoding is deprecatedvar_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 也为我们供应了几个用于字符串操作的函数。
echo iconv_strlen("测试长度测试长度"), PHP_EOL; // 8echo iconv_strlen("测试长度测试长度", 'ISO-8859-1'), PHP_EOL; // 24echo iconv_strlen("测试长度测试长度", 'GBK'), PHP_EOL; // 12echo '======', PHP_EOL;echo iconv_strpos("测试长度测试长度", "长"), PHP_EOL; // 2echo iconv_strpos("测试长度测试长度", "长", 0, 'ISO-8859-1'), PHP_EOL; // 6echo iconv_strpos("测试长度测试长度", "长", 0, 'GBK'), PHP_EOL; // echo '======', PHP_EOL;echo iconv_strrpos("测试长度测试长度", "长"), PHP_EOL; // 6echo iconv_strrpos("测试长度测试长度", "长", 'ISO-8859-1'), PHP_EOL; // 18echo '======', 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() 函数的利用的了,实在它反而没什么可讲的,将指定的编码转换成其余一种编码而已,相信这个函数大家都不陌生。
$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 头的利用也非常广泛。如果做过邮件发送吸收干系的开拓并且抓过包的同学一定见过下面的内容。
headers_string = <<<EOFSubject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=To: example@example.comDate: Thu, 1 Jan 1970 00:00:00 +0000Message-Id: <example@example.com>Received: from localhost (localhost [127.0.0.1]) by localhost with SMTP id example for <example@example.com>; Thu, 1 Jan 1970 00:00:00 +0000 (UTC) (envelope-from example-return-0000-example=example.com@example.com)Received: (qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000EOF;
Subject 字符便是邮件的标题,To 便是发送人的邮件地址。在这里我们紧张看一下 Subject 的内容,它的开头就有一段描述这个字段利用的编码信息的内容,?UTF-8 ,然后后面是一堆看不懂的东西。实在我们大略地能看出来这是一个 base64 编码的内容,如果将它解码在对应的编码内容下就能看到原文信息。不过,这个时候我们也可以利用 iconv 来直接转换它的编码。
$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) "example@example.com"// ["Date"]=>// string(30) "Thu, 1 Jan 1970 00:00:00 +0000"// ["Message-Id"]=>// string(21) "<example@example.com>"// ["Received"]=>// array(2) {// [0]=>// string(204) "from localhost (localhost [127.0.0.1]) by localhost with SMTP id example for <example@example.com>; Thu, 1 Jan 1970 00:00:00 +0000 (UTC) (envelope-from example-return-0000-example=example.com@example.com)"// [1]=>// string(57) "(qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000"// }// }
看到了么?不仅直接转了编码,而且还将 mime 头格式转换成了 PHP 中的数组格式。当然,我们这里测试的代码是将正常的内容转换到 ISO-8859-1 了,反而是涌现了乱码。下面我们再拿一个中文邮件的例子来看下。
$headers_string = <<<EOFReturn-Path: <bluesky7810@163.com>Delivered-To: bhw98@sina.comReceived: (qmail 75513 invoked by alias); 20 May 2002 02:19:53 -0000Received: from unknown (HELO bluesky) (61.155.118.135) by 202.106.187.143 with SMTP; 20 May 2002 02:19:53 -0000Message-ID: <007f01c3111c$742fec00$0100007f@bluesky>From: "=?gb2312?B?wLbAtrXEzOwNCg==?=" <bluesky7810@163.com>To: "bhw98" <bhw98@sina.com>Cc: <bhwang@jlonline.com>Subject: =?gb2312?B?ztK1xLbgtK6/2rPM0PI=?=Date: Sat, 20 May 2002 10:03:36 +0800MIME-Version: 1.0Content-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) "<bluesky7810@163.com>"// ["Delivered-To"]=>// string(14) "bhw98@sina.com"// ["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) ""蓝蓝的天// " <bluesky7810@163.com>"// ["To"]=>// string(24) ""bhw98" <bhw98@sina.com>"// ["Cc"]=>// string(21) "<bhwang@jlonline.com>"// ["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 字段进行转码。
echo iconv_mime_decode("Subject: =?gb2312?B?ztK1xLbgtK6/2rPM0PI=?=", 0, 'UTF-8'), PHP_EOL; // Subject: 我的多串口程序
除了对付吸收的信息进行编码转换之外,我们还可以自己编码干系的内容进行发送利用。
$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