首页 > PHP > PHP编码识别与转换

PHP编码识别与转换

PHP可以通过iconv或mb扩展来处理不同的编码(国内主要分utf-8编码和gbk或gb2312这三种编码),可是这2个扩展不能随便使用,首先需要知道待处理字符串的编码才能使用相关的编码转换函数。

PHP手册上使用最广泛的当属is_utf8函数:

/**
 * 判断输入字符的编码是否是UTF8
 * @param string $string
 * @return bool
 */
function is_utf8($string)
{
	return !strlen(
	preg_replace(
	  ',[\x09\x0A\x0D\x20-\x7E]'            # ASCII
	. '|[\xC2-\xDF][\x80-\xBF]'             # non-overlong 2-byte
	. '|\xE0[\xA0-\xBF][\x80-\xBF]'         # excluding overlongs
	. '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'  # straight 3-byte
	. '|\xED[\x80-\x9F][\x80-\xBF]'         # excluding surrogates
	. '|\xF0[\x90-\xBF][\x80-\xBF]{2}'      # planes 1-3
	. '|[\xF1-\xF3][\x80-\xBF]{3}'          # planes 4-15
	. '|\xF4[\x80-\x8F][\x80-\xBF]{2}'      # plane 16
	. ',sS',
	'', $string));
}

使用方式很简单,首先建立一个编码为utf-8的php脚本,内容如下:

<?php
$str = '中文UTF-8';
//bool(true)
var_dump(is_utf8($str));

待检测的字符串是写在utf-8的脚本上的,所以是utf-8编码。

然后将该php脚本编码保存为ANSI编码(gbk编码或其他),然后再次运行,打印出bool(false)。

一般用于接收客户端传来的参数值编码检测,例如客户端传递过来的$_GET['content']为评论内容编码可能会不一致,即使前段设计再精妙,也难免会接收到非utf-8编码的内容,这时就可以用is_utf8来检测,如果不符合则通过iconv或mb_convert_encoding进行转码。

不过,这个函数也有一些小bug,已知的bug有遇到"要","营业"等词时会一直返回true,例如:

建立编码为gbk的php脚本,内容如下:

<?php
$str = '要';
//bool(true)
var_dump(is_utf8($str));
$str = '要求';
//bool(false)
var_dump(is_utf8($str));

当遇到单个字的gbk编码的'要'时,返回true,遇到多个字后,返回false,说明检测有问题,不过对于评论系统这样要求提交评论的长度情况下可以忽略。


另外,附上最近比较常用的编码转换函数,目前国内测试均正常。

/**
 * gbk编码转换为utf8函数,依赖mb_convert_encoding或iconv
 * @param string $string
 * @return string
 */
function gb_convert_utf8($string)
{
	if(function_exists('mb_convert_encoding'))
	{
		return mb_convert_encoding($string, 'UTF-8', 'GBK');
	}
	return iconv('GBK', 'UTF-8//IGNORE', $string);
}

/**
 * 编码由utf8转换为gbk函数
 * @param string $string
 * @return string
 */
function utf8_convert_gb($name)
{
	if(function_exists('mb_convert_encoding'))
	{
		return mb_convert_encoding($name, 'GBK', 'UTF-8');
	}
	$tostr = '';
	for ($i = 0; $i < strlen($name); $i++)
	{
		$curbin = ord(substr($name, $i, 1));
		if($curbin < 0x80)
		{
			$tostr .= substr($name, $i, 1);
		}else if ($curbin < bindec('11000000'))
		{
			$str = substr($name, $i, 1);
			$tostr .= '&#' . ord($str) . ';';
		}else if ($curbin < bindec('11100000'))
		{
			$str = substr($name, $i, 2);
			$tostr .= '&#' . $this->GetUnicode($str) . ';';
			$i += 1;
		}else if ($curbin < bindec('11110000'))
		{
			$str  = substr($name, $i, 3);
			$gstr = iconv('UTF-8', 'GBK//IGNORE', $str);
			if(!$gstr)
			{
				$tostr .= '&#' . $this->GetUnicode($str) . ';';
			}else{
				$tostr .= $gstr;
			}
			$i += 2;
		}else if ($curbin < bindec('11111000'))
		{
			$str = substr($name, $i, 4);
			$tostr .= '&#' . $this->GetUnicode($str) . ';';
			$i += 3;
		}elseif($curbin < bindec('11111100'))
		{
			$str = substr($name, $i, 5);
			$tostr .= '&#' . $this->GetUnicode($str) . ';';
			$i += 4;
		}else{
			$str = substr($name, $i, 6);
			$tostr .= '&#' . $this->GetUnicode($str) . ';';
			$i += 5;
		}
	}
	return $tostr;
}

/**
 * utf8_convert_gb依赖方法
 * @param string $str
 * @return string
 */
function GetUnicode($str)
{
	$temp = '';
	for($i = 0; $i < strlen($str); $i++)
	{
		$x = decbin(ord(substr($str, $i, 1)));
		if ($i == 0)
		{
			$s = strlen($str) + 1;
			$temp .= substr($x, $s, 8 - $s);
		} else {
			$temp .= substr($x, 2, 6);
		}
	}
	return bindec($temp);
}



本文地址:http://blog.zhengshuiguang.com/php/encode-convert.html

转载随意,但请附上文章地址:-)

标签:编码 转换 is_utf8 php转码

评论已关闭