打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
UTF-8编码的前世今生

概述

在不远的曾经,如果应用需要支持国际化(i18n),则需要应用程序能够使用不同的字符集和编码输入、存储和输出数据。 不同的字符集都可以展现和编码定义好的字符,但是一个字符集不能使用另一个字符集来显示。 当人们受不了这种不兼容时,人们开始考虑使用一种标准的字符集和编码来统一这个世界。 于是,在1991年,Unicode产生了。 它涵盖了所有已知的可写语言的所有字符的字符集。而UTF-8编码只是UNICODE的一种变长度的编码表达方式。

维基百科中对于UTF-8编码的解释是: UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码(定长码), 也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容, 这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。

UTF-8适用于紧凑地存储拉丁字母。UTF-8编码的一个优点是它可以编码成字节流,这样可以将透明化底层的体系架构。

UTF-8字节布局

字节数位数UTF-8字节流
170xxxxxxx
211110xxxxx 10xxxxxx
3161110xxxx 10xxxxxx 10xxxxxx
42111110xxx 10xxxxxx 10xxxxxx 10xxxxxx
526111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6311111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
73611111110 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
84211111111 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

关于BOM

BOM是Byte Order Mark的简称, 它出现在Unicode流的开头部分,用来说明编码类型。因为系统可能是big endian,也可能是little endian, 或者是多字节的Unicode编码.把BOM放置在文件开头部分,利用它来判断字节序。

在UTF-8编码中,BOM没有太大的意义,并且不推荐使用它。在HTML或XML的文件开头放置BOM,可能会导致无法解析。 在PHP中,如果头部有BOM,则可能会出现网页头部多一行、导致网页出现乱码或者其它不可预知的错位或错误, 因此,我们应该避免在PHP模板文件或源码代码文件的开头放置BOM。 但是Windows下,有些程序会默认给utf-8文件添加BOM,此时需要手动清除BOM头, 如果此类文件太多,可以考虑写程序遍历指定目录下所有文件,清除开头的BOM.

使用UTF-8编码

输出UTF-8编码文件

如果要告诉浏览器你输出的编码格式,在PHP中可以使用:

 header("Content-Type: text/html; charset=utf-8");

除了这种PHP的方式,也可以使用meta标签设置编码:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

对于xml文档,它可以直接支持编码作为xml的一部分。

<?xml version="1.0" encoding="utf-8" ?>

PHP中的UTF-8编码支持

在PHP中,内置的字符串函数并不支持多字节的字符串,Unicode需要mbstring扩展支持,此扩展重载了现有的字符串处理函数。 PHP6计划将Unicode支持内置到语言中。

Mysql中的utf-8

如果我们的Mysql是使用utf-8编码,则在执行查询前经常会使用

SET names utf8;

它的作用相当于执行下面的三条语句:

SET character_set_client = utf8;SET character_set_results = utf8;SET character_set_connection = utf8;

在应用中出现编码问题,一个比较笨却有效的办法是将PHP文件,mysql客户端,mysql服务器端,前端页面,全部统一用utf-8编码。 另外在phpMyAdmin中有多种字符集,其中utf8_unicode_ci和utf8_general_ci是最常用的, 但是utf8_general_ci对某些语言的支持有一些小问题,如果可以接受, 那最好使用utf8_general_ci,因为它速度快。否则,请使用较为精确的utf8_unicode_ci,不过速度会慢一些。

识别UTF-8编码

在应用开发过程中,如果需要验证输入是否为UTF-8序列,则可能需要写代码实现相关功能。 虽然我们可以指定前端页面为UTF-8,但是我们并不能控制到服务器的数据一定是从指定的页面发送的。 因此,我们需要识别UTF-8编码。

/** * 识别UTF-8编码 判断一个字符串是否为utf-8编码 2011-04-18 sz * @author phppan.p#gmail.com * http://www.phppan.com * 哥学社成员(http://www.blog-brother.com/) * TIPI团队成员(http://www.php-internal.com/) * @package blog *//** * 判断一个字符串是否为utf-8编码 方法一 * 依据UTF-8编码的字节布局,以逆向思维,通过判断其不是UTF-8编码来判断正确性。 * 此算法来源于<<Building Scalable Web Sites>> * @param <type> $string */function is_utf8($string) {    $pattern = '[\xC0-\xDF]([^\x80-\xBF]|$)'; //  匹配110xxxxx,其后应该有1个字节,如果此字节无法匹配10xxxxxx,或为结束符,则不是utf-8    $pattern .= '|[\xE0-\xEF].{0,1}([^\x80-\xBF]|$)'; //匹配1110xxxx,其后应该有2个字节,    $pattern .= '|[\xF0-\xF7].{0,2}([^\x80-\xBF]|$)';//匹配11110xxx,其后应该有3个字节,    $pattern .= '|[\xF8-\xFB].{0,3}([^\x80-\xBF]|$)';//匹配111110xx,其后应该有4个字节,    $pattern .= '|[\xFC-\xFD].{0,4}([^\x80-\xBF]|$)';//匹配1111110x,其后应该有5个字节,    $pattern .= '|[\xFE-\xFE].{0,5}([^\x80-\xBF]|$)';//匹配1111110,其后应该有6个字节,    $pattern .= '|[\x00-\x7F][\x80-\xBF]';    $pattern .= '|[\xC0-\xDF].[\x80-\xBF]';    $pattern .= '|[\xE0-\xEF]..[\x80-\xBF]';    $pattern .= '|[\xF0-\xF7]...[\x80-\xBF]';    $pattern .= '|[\xF8-\xFB]....[\x80-\xBF]';    $pattern .= '|[\xFC-\xFD].....[\x80-\xBF]';    $pattern .= '|[\xFE-\xFE]......[\x80-\xBF]';    $pattern .= '|^[\x80-\xBF]';    return preg_match("!$pattern!", $string) ? FALSE : TRUE;}/** * 网上流传的一个验证方法 方法二 * @link http://www.w3.org/International/questions/qa-forms-utf-8.en.php * @param <type> $string * @return <type> */function is_utf8($string) {    $pattern = '/^(?:';    $pattern .= '[\x09\x0A\x0D\x20-\x7E]';             # ASCII    $pattern .= '|[\xC2-\xDF][\x80-\xBF]';             # non-overlong 2-byte    $pattern .= '|\xE0[\xA0-\xBF][\x80-\xBF]';         # excluding overlongs    $pattern .= '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}';  # straight 3-byte    $pattern .= '|\xED[\x80-\x9F][\x80-\xBF]';         # excluding surrogates    $pattern .= '|\xF0[\x90-\xBF][\x80-\xBF]{2}';      # planes 1-3    $pattern .= '|[\xF1-\xF3][\x80-\xBF]{3}';          # planes 4-15    $pattern .= '|  \xF4[\x80-\x8F][\x80-\xBF]{2}';    $pattern .= ')*$/xs';    return preg_match($pattern, $string);}/** * 判断字符串是否为utf8编码 方法三 * @param <type> $string * @return <type> */function is_utf8($string) {    if (preg_match("/^([" . chr(228) . "-" . chr(233) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}){1}/", $string) == TRUE            || preg_match("/([" . chr(228) . "-" . chr(233) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}){1}$/", $string) == TRUE            || preg_match("/([" . chr(228) . "-" . chr(233) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}[" . chr(128) . "-" . chr(191) . "]{1}){2,}/", $string) == TRUE    ) {        return TRUE;    }    return FALSE;}

第一种和第二种基本类似,结果也基本类似,但是对于“营业”等字符串无法准确的识别。 第三种方法对于上面提到的字符串可以正确识别,但是对于“欧舒丹”等字符串却无法识别。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
UTF-8字符集基础
unicode和MBCS(多字节字符集)的关系
存文本文件及其字符编码
字符集与编码[下]
常见编码总结:Unicode、UTF、ISO 8859
05.编码番外篇-图解base64编码,BOM,转换,关系等
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服