PHP处理各种字符串时有时会碰到乱码的问题,其实我们在开发实践中只要坚持一个原则:编辑代码、存储数据、输出数据等都统一使用UTF-8编码。坚持这个原则会规避很多字符串乱码的问题。
PHP有mbstring扩展,自带几种字符串截取函数,其中常用到的就是 substr 和 mb_substr。
当操作 Unicode 字符集的时候,使用相应的函数代替原生的字符串函数。举个例子,一个文件编码为 UTF-8 的 PHP 代码,假如使用 strlen() 函数是错误的,请使用 mb_strlen() 函数代替。
如果你使用substr截取中文字符时会出现乱码,这是因为substr是按字节来截取的。即UTF-8编码的中文,使用substr截取,只会截取1/3个中文,当然出现乱码了。UTF-8编码时,一个汉字是3个字节。同样其他国家不同语言文字会产生多字节字符串问题,所以我们统统使用mb_strlen()来处理。
如果不清楚字符串的编码格式的话,可以用mb_detect_encoding检查。
如果要转换编码,使用函数iconv(),如GB2312 转UTF-8:
iconv("GB2312","UTF-8",$text);
当遇到无法确定原编码是何种编码,或者iconv转化后无法正常显示时可用mb_convert_encoding 函数。
$str = mb_convert_encoding($str, "UTF-8");
其实在php.ini中有个选项设置default_charset = "UTF-8";,很多字符串处理函数如htmlentities()会使用这个默认字符集。
我们可以使用header()函数明确指定字符集,在PHP返回的响应中,Content-Type首部默认也使用这个值。
header("Content-Type: text/html;charset=utf-8");
当然,我们在创建HTML文档的头部也应该加入这个mata标签:
<meta charset="UTF-8" />
虽然我们将php代码、输出数据时都使用UTF-8,但是可能还会遇到很多诡异现象。比如,我遇到的坑,当要从服务器上下载一个文件时,IE浏览器、Edge在下载中文文件名时会乱码,还有当文件名包含空字符时,下载后的文件名称空格变成了+号等等这些诡异现象。
其实,PHP通过 header() 函数下载文件的时候,也要考虑浏览器和操作系统(大部分人使用的是 Windows),对于 Chrome 来说,输出的文件名编码可以是 UTF-8,Chrome 会自动将文件名转换为 GBK 编码。
而对于IE 来说,它继承了操作系统的环境,所以下载文件名假如是中文必须转码为 UTF-8 编码,否则下载的时候用户看到的是乱码文件名。 解决办法有了:
$agent=$_SERVER["HTTP_USER_AGENT"]; if(strpos($agent,'MSIE')!==false ){ $filename = iconv("UTF-8","GBK","中文附件.pdf"); header("Content-Disposition: attachment; filename=\"$filename\""); }
首先保证你的 Mysql 都是 UTF-8。然后 Mysql 客户端连接的时候也保持 UTF-8,具体到 PHP 中,就是 mysqli 或者 PDO 扩展连接 Mysql 的时候都设置 UTF-8 作为连接编码,两边保持一致,一般就不会遇到乱码问题。
例如使用PDO链接Mysql时,使用UTF-8字符集:
$pdo->query('SET NAMES utf8;');
1.处理多字节字符串时一定要知道数据的字符编码;
2.使用UTF-8字符编码存储数据;
3.使用UTF-8字符编码输出数据。