`
qtlkw
  • 浏览: 307213 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Web开发中的字符集问题

 
阅读更多
很多人在开发网站开始阶段没有注意到字符集统一的重要性,因此开发的网站不是数据库中存有乱码就是web页面显示为乱码。现以web开发中的字符集为主体讨论在个人和团队web开发中需要注意的问题,和相应的解决方法。

1. 常见问题的解决<o:p></o:p>

比如我在网站开发阶段就遇到两个严重的问题:

我使用的是Zend studio的开发工具,保存代码时也是默认保存的,没有注意到字符集的问题,开始一切正常,但是当我想在页面中添加’©’这个符号的时候,网页不能正常显示。后来发现,zend 默认的保存编码是gb2321编码,而这个编码中不能表示以上那个字符,要显示那个字符有两种方式,一种是使用php中的图形函数,将copyright字符转换为图形显示在网页上。第二种方法是将网站格式完全转化为utf-8编码。我采用的是后者,将全部页面保存为utf-8格式,然后在content-type中将charset=转换为utf-8;

<o:p> </o:p>

第二个严重的问题是数据库的乱码问题。再将文章存入数据库中后,使用phpmyadmin查看其中数据显示的也全部是乱码,起初没有对这个完全正视起来,因为在php使用其中数据时没有出现异常,在网页中显示正常。但是这本就是个严重的隐患,因此今天想办法解决了,解决方法使用的是很笨的方法,将数据库中的数据读出来,存入表中,然后写一个安装文件(使用php),再连接数据库后,添加一段代码,效果如下:

$conn=new mysqli(hostname,username,passwd,dbname);

$conn->query(‘set names \’utf8\’);

这样在将php的安装文件中的数据写入数据库时就不会出现编码不一致的问题。在phpMyadmin中也能正常显示了。

<o:p> </o:p>

<o:p> </o:p>

2.原理介绍<o:p></o:p>

(摘自阿强的blog: http://www.phpchina.com/10458/viewspace_4782.html)<o:p></o:p>

1. Collations
Collations翻成中文是“校验”,在网页开发的过程中,这个词汇,只在Mysql里使用,主要作用是指导Mysql对字符的比较,比如, ASCII字符集里,Collations规定了a小于b,a等于a,以及a是否等于A之类的。通常,大家基本可以忽略Collations的存在,因为每个字符集都有一个默认的Collations,通常,使用默认的Collations就可以了。以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?<o:p></o:p>

2.字符集
与这对比的是,字符集是个更广的概念,即使是Windows下普通的文本文件,也渗及到字符集的问题。不同的字符集,规定了不同的字符的编码方式。一个 character set (字符集)是一组符号和编码,比如,ASCII字符集,包括的字符有:数字,大小写字母,分号、换行之类的符号,编码方式是用一个7bit表示一个字符(A的编码是65,b的编码是98)。ASCII只规定了英文字母的编码,非英文语言不能用ASCII编码表示,为此,不同的国家,都为自己的语言做了编码,比如,我们国家,就有GB2312编码。但每个国家之间的编码不同,也存在着一些跨平台的问题,为此,一些国际化标准组织,就制定了一些国际通用的编码,最常用的就是UTF8了。ASCII只对英文符号和英文字母做了编码,GB2312对英文符号,英文字母,汉字做了编码,UTF8对世界上所有的语言文字做了编码,所以,GB1212的字符包含了ASCII字符,UTF8包含了GB2312字符。由此可见,UTF8是所含最广字符的字符集,所以,在一些多语言的WEB系统中,一般用UTF8字符集(PHPMyAdmin使用UTF8编码)。
任何文本的存储,都渗及到字符集的概念。包括数据库,也包括普通的文本文件。
主要术语:
字符:汉字,英文字母,标点符号,拉丁文等等。
编码:将字符转换成计算机存储的格式,比如,A用65表示
字符集:一组字符以及对应的编码方式。

a. Mysql的字符集
Mysql目前支持多字符集,并且,支持在不同的字符集之间转换(便于移植和支持多语言)。
Mysql可以设置服务器级字符集、数据库级字符集、数据表级字符集、表列的字符集,实际上,最终使用字符集的地方是存储字符的列,比如,你设置 table1中col1列是字符类型,col1才用到了字符集,如果table1表的col2列是int类型,col2不使用字符集的概念。
服务器级字符集、数据库级字符集、数据表级字符集都是为列的字符集做默认选项的。
Mysql一定有一个字符集,可以通过启动时加参数指定,也可以编译时指定,也可以在配置文件里指定。Mysql服务器字符集,只是做为数据库级的默认值。创建数据库时,你可以指定字符集,如果没指定,就使用服务器的字符集。同理,创建表时,你可以指定表级的字符集,如果没指定,使用数据库的字符集做为表的字符集。创建列时,你可以指定某列的字符集,如果没指定,就使用表的字符集。
通常情况下,您只需设置服务器级的字符集,其它的数据库级,表级,以及列级的字符集,都继承自服务器级字符集。
由于UTF8是最广的字符集,所以,一般情况下,我们设置Mysql服务器级的字符集为UTF8!

b. 普通文本的字符集问题
任何文本的存储,都存在着字符集的问题,普通文本文件也不例外。
Windows2000+的系统中,打开记事本,“保存为…”对话框,就有一个选项,可以让你选择存储文本的编码方式。
通常情况下,大家都使用Windows2000+的系统,都使用默认的编码,所以,不会碰到字符集的问题。
Windows下,保存文本文件时,可以选择编码方式,但打开文本文件时,都是自动判断编码方式的。网上有一个用Windows2000+的记事本玩移动,联通的笑话,大家可以搜搜,就是因为Windows在打开文本文件时,编码判断错误引起的问题。
因为自动判断编码有时会错误,所以,有的文本文件,规定了如何识别自身所使用的编码。HTML文件就是一个这样的例子。>
HTML是文本文件。存储HTML文件的时候,需要使用一个编码,并且,在HTML文件里,也使用HTML语法,指定了该文件所使用的编码(比如< meta http-equiv="content-type" content="text/html; charset=UTF-8">)。如果HTML文件没有指定编码,则浏览器自动识别文件的编码。如果HTML指定了编码,则浏览器使用HTML指定的编码。
通常情况下,HTML文件指定的charset和HTML文件自身的编码是一致的,但也有不一致的情况,如果不一致,就会导致网页乱码(此处乱码,只和文本文件有关,和数据库无关。)使用专门的网页编辑工具(比如Dreamwave),会自动根据网页中的charset值来编码文件。

c. php+mysql的字符集问题
PHP最终生成的是文本文件,但他要取数据库里的文本,或将文本存进数据库
由于Mysql支持多字符集,默认情况下,Mysql不知道PHP发给他的是什么编码的字符,所以,Mysql要求客户端(PHP)告诉他存取的字符集是什么。 
PHP通过设置character_set_client,告诉Mysql,PHP存进数据库的是什么编码方式。
PHP通过设置character_set_results,告诉Mysql,PHP需要取什么样编码的数据。
PHP通过设置character_set_connection,告诉Mysql,PHP查询中的文本,使用什么编码。
MYSQL使用设置的编码方式存储文本。
假设Mysql使用setserver来存储文本,PHP的character_set_client是setclient,PHP的character_set_results是setresult。那么,Mysql将PHP发来的文本,从setclient编码方式,转换成 setserver编码方式,再存入数据库,如果PHP取文本,Mysql将文本从setserver转换成setresult,再发送给PHP。
PHP文件(最终生成的HTML文件)本身有个编码,如果Mysql传过来的编码,与PHP文件自身的编码不同,那么,整个网页,必然乱码。所以,PHP一般将自己的编码方式,告诉Mysql。
要保证不乱码,就必须将三个编码统一:一是网页自身的编码,二是HTML里指定的编码,三是PHP告诉Mysql的编码(包括character_set_client和character_set_results)。
第一和第二个编码,如果使用DW之类的编辑器写的网页,通常是一致的,但用记事本写的网页,有可能不一致。(这里我感觉不太准确,需要讨论一下)
第三个编码,需要手工通知Mysql。这步可以通过在PHP里使用mysql_query(“set names characterX”)来实现。

d.字符集的转换问题
如果小字集转换成大字符集,不会丢失数据,但大字集,转换成小字集,可能会丢失数据。
比如,UTF8里有的字符,GB2312不一定有,所以,从UTF8转换到GB2312可能会丢失一些字符。
但有种情况例外,先从GB2312转成UTF8,再从UTF8转成GB2312,这种情况是不会丢数据的,因为,刚开始转换的文本,都是GB2312里的字符,所以,整个过程都是GB2312的字符在转换,不会丢失。
正因为UTF8能容纳世界上的所有字符,所以,数据库一般使用UTF8编码。这使得,任何字符都可以存进UTF8编码的数据库。

e. PHPMyAdmin乱码的问题
PHPMyAdmin支持多国语言,这就必定要求HTML页面使用UTF8编码。
HTML页面使用UTF8编码,这就必定要求PHPMyAdmin连接Mysql时,character_set_client和character_set_results使用UTF8编码。
当前情况下,PHP连接Mysql只能是使用set names(或其它几个语句)来通知Mysql的编码方式,如果没有显式的声明编码方式,都将使用latin1编码。一般的程序,都没有显式声明 character_set_client变量,所以,都是将gb2312文本,按latin1编码方式存在数据库,PHPMyAdmin再用utf8格式读取,肯定是乱码的。
如果PHP程序按正确的编码存入数据库,肯定是没有问题的。所以,需要修改的不是PHPMyAdmin.(虽然有时修改PHPMyAdmin可以解决乱码问题,但这不是问题的根本)

补充:
(参考:http://blog.csdn.net/fmddlmyy/archive/2005/05/04/372148.aspx)

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:<o:p></o:p>

在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。<o:p></o:p>

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。<o:p></o:p>

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。<o:p></o:p>

Windows就是使用BOM来标记文本文件的编码方式的。

<o:p> </o:p>

讨论:<o:p></o:p>

第一和第二个编码,如果使用DW之类的编辑器写的网页,通常是一致的,但用记事本写的网页,有可能不一致。<o:p></o:p>

如果在dw中选择了:“包括Unicode签名(Bom)”那么,保存的和记事本保存的是一样的,都是前面多出三个字节。这三个字节在网页显示时有特殊的作用,如果这样保存一个网页,在html中不需要指定utf-8格式,浏览器就自动选用utf8编码,而且浏览者不能自己修改成其他的编码格式。如此保存在开发中可能是一个既保险又提高效率的好方法,但是考虑到他和其他很多开发工具的不兼容(zend中没有这个功能,而且显示代码的时候,将前三个字符显示为点,在editplus中全部显示为乱码。所以不推荐选用bom。<o:p></o:p>

<o:p> </o:p>

3.团队中的字符集的同步<o:p> </o:p><o:p> </o:p>

我们推荐使用utf-8字符集,因为此字符集将所有字符都包含了进去,因此以后不会再担心字符表示不了的问题。

但是如何在团队开发重视全部参与编码的成员都保证自己的字符是utf-8编码的?我们需要考虑这些方面:开发工具的默认编码(也就是网页的编码),html中指定的编码,和php指定的编码,数据库的编码。

<o:p></o:p>

对于开发工具默认的编码,需要考虑美工的开发工具和编程人员的开发工具,最普遍的为dreamweaver和zend studio,最一劳永逸的方式不是在每次保存时指定编码格式,而是在编程工具的选项或者是首选项中指定字符集编码,对于dreamweaver,打开”编辑”菜单,选择“首选参数”(或Ctrl+U),选择“新建文档”分类(如下),在默认编码中选择如图的utf-8,然后将下面的“当打开未指定的…”,在unicode标准化表单中选择c类,但是不要选择下面的“包括unicode签名”,具体问什么,上面已经说了。这样在每次保存的时候,就默认保存为utf编码。<o:p></o:p>

<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><v:shape id="_x0000_i1025" style="WIDTH: 375pt; HEIGHT: 261pt" type="#_x0000_t75" alt="" o:button="t"><v:imagedata src="file:///F:\DOCUME~1\xombat\LOCALS~1\Temp\msohtml1\01\clip_image001.gif" o:href="http://www.cnbruce.com/blog/uploadfile/GIF/2006-7/28-16727-dw-utf-8.gif"></v:imagedata></v:shape>

对于php开发人员,使用zend ,选择tool->preference…进入preference对话框,选择Desktop标签,然后在Encoding文本框中选择UTF-8.在进入Debug标签,从中选定define server out put encoding ,然后在后面的文本框中选择utf-8(这一步主要是为了在zend开发环境中调试而用)

<o:p></o:p>

html中指定的编码

保存的文本是utf-8的还不够,我们还需要在html中指定编码类型,具体有两种方法,可以任选其一:

Html代码方法:在标签中加入这一行: <meta http-equiv="content-type" content="text/html; charset=UTF-8">

Php代码方法:在输出任何数据之前,加入这行代码:header(‘content-type:text/html;charset=utf<st1:chmetcnv tcsc="0" numbertype="1" negative="True" hasspace="False" sourcevalue="8" unitname="’" w:st="on">-8’</st1:chmetcnv>);

两种方法任选其一。<o:p> </o:p>

Php指定编码:

需要在连接好数据库后,加入如下一行代码,

$conn->query(‘set names \’utf8\’);

具体见第一部分问题解决。<o:p> </o:p>

数据库的编码:

这里数据库的编码,指的是数据库中默认的编码。 默认的编码方式使用php的函数可以查看(连接数据库后,$charset=$conn->character_set(),也可以通过查看mysql系统变量来查看; $charset就是编码类型的信息)。设定数据库的默认编码方式是在mysql 程序文件的my.ini中修改如下的指令:

将所有的都改为:default-character-set=utf8

在mysqld下面添加:default-collation=utf8_general_ci(其实这行不添加也可以,utf-8默认的就是这个)

可以参阅:http://phpbb-tw.net/phpbb/viewtopic.php?t=41148&highlight=&

但不要学着他将已经保存数据的表用alter进行转换。

<o:p></o:p>至此完。
分享到:
评论

相关推荐

    Web开发字符集相关知识

    Web开发中的字符集和字符编码是确保正确显示和处理文本数据的关键因素,特别是在涉及多语言和特殊字符时。本文将深入探讨字符集、字符编码、Web浏览器端的处理方式、Web服务器端的处理方式以及数据库的字符编码设置...

    java 中文问题(java web 开发中的中文问题)

    Java 中文问题是 Java web 开发中常见的一种问题,解决该问题需要了解 Java 中文编码、字符集和过滤器的使用。本文将总结 Java 中文问题的解决方法,并提供实践经验和代码示例。 一、支持中文 在 Java 中,支持...

    SSH+mysql开发字符集问题

    ### SSH+MySQL开发中的字符集问题详解 #### 一、问题背景 在使用MySQL与SSH框架进行开发过程中,中文字符的乱码问题是非常常见的。尤其是对于新手开发者来说,这一问题可能会耗费大量的时间与精力去解决。本文将...

    解决Mysql数据库在web开发中乱码问题

    在Web开发中,尤其是使用MySQL...总之,解决MySQL数据库在Web开发中的乱码问题,关键在于保持字符集设置的一致性和正确性,从源头做起,覆盖数据处理的全过程,才能从根本上消除乱码现象,提升用户体验和系统的稳定性。

    JAVA及相关字符集编码问题

    在实际开发中,应根据具体需求选择合适的字符集编码,并注意在不同环节保持字符集编码的一致性,以避免乱码和其他潜在问题。通过上述对JAVA及相关字符集编码问题的深入探讨,希望能帮助开发者们更好地理解和应对这一...

    解决web开发中的中文问题.doc

    ### 解决Web开发中的中文问题 在Web开发过程中,中文乱码问题是非常常见的一个问题,尤其对于使用Tomcat服务器的应用程序来说。本篇文章将详细介绍导致这一问题的原因以及如何解决这一问题。 #### 一、问题背景与...

    Java Web程序开发中字符乱码的原因与解决办法.pdf

    字符乱码问题是Java Web程序开发过程中经常遇到的一个问题,它会对用户界面的友好性以及信息的准确传达造成很大的影响。为了解决这个问题,我们首先要了解字符集和字符编码的相关知识,然后分析字符乱码的原因,并...

    Java Web程序开发中字符乱码的原因与解决办法.zip

    在Java Web程序开发中,字符乱码是一个常见的问题,它主要出现在输入输出、编码转换以及数据库存储等环节。本文将深入探讨字符乱码产生的原因,并提供相应的解决策略。 首先,我们要理解字符编码的基础知识。字符...

    Java Web开发常见问题.pdf

    ### Java Web开发中常见的中文乱码问题解析 在Java Web开发过程中,中文乱码问题是开发者经常遇到的一个挑战。这些问题主要源于Java默认的Unicode编码与HTML页面及表单默认的Latin-1编码之间的不兼容,以及在不同的...

    字符集编码

    在Web开发中,字符集编码问题经常成为开发者需要解决的关键技术挑战之一。不同语言、不同系统间的字符编码差异可能导致数据在传输过程中出现乱码等问题。因此,理解字符集编码的基本原理及如何在实际开发中正确配置...

    Java WEB开发中的中文乱码问题解决方法.pdf

    在Java Web开发中,中文乱码问题一直是开发人员面临的常见问题之一。中文乱码通常是由于在字符编码转换过程中,字符集不一致或设置不当所导致。为了解决这一问题,首先需要了解Java Web工程字符编码的基本理论,包括...

    Web学习之常用特殊字符表

    Web学习中常用的特殊字符,细节很重要,方便您随时查阅和学习,大大摆脱记忆短缺的尴尬,有效提升Web开发工作

    iconv字符集转换库

    iconv字符集转换库是计算机编程领域中一个重要的工具,主要用于在不同的字符编码之间进行转换。这个库在处理多语言环境、数据交换以及网络通信时起着至关重要的作用。字符集,也称为字符编码,是一种将字符与数字或...

    解析WEB开发编码问题

    在Web开发中,编码问题至关重要,因为它涉及到如何正确地处理和传输文本信息。计算机系统处理数据的基本单位是字节,而人类理解的是字符串,这就需要字符集来建立两者之间的桥梁。字符集定义了每个字符如何映射为...

    MYSQL字符集与乱码问题分析

    Web开发中,HTML和PHP需正确声明字符集,一般推荐使用UTF-8,以确保网页内容在不同平台和浏览器上的正确显示。 ### MySQL中的字符集 #### 数据类型 MySQL支持多种字符集,如latin1、utf8、utf8mb4等,每种字符集...

    web开发中的中文问题

    在web开发中,中文问题是一个常见的挑战,尤其是在处理文本数据、网页显示以及用户交互时。中文字符编码的处理不当往往会导致乱码、显示不全或者无法正确存储等问题。本篇文章将深入探讨这个问题,并提供解决方案。 ...

    Java中的字符集编码入门(二)编码字符集与字符集编码的区别[参考].pdf

    在Java开发中,处理字符串时,我们需要关注字符集编码问题,特别是在读写文件、网络传输或者数据库操作中。使用不当可能导致乱码问题。Java提供了java.nio.charset包来处理字符编码,例如使用Charset类进行编码和...

    MySQL数据库字符集的问题研究.pdf

    在实际操作MySQL数据库的过程中,常见的字符集问题主要包括: 1. **数据库中的中文字符乱码显示**。 2. **Web页面显示数据库中的中文字符时出现乱码**。 3. **无法正确存储一些特殊字符,如emoji表情**。 #### 五...

    web 开发中遇到的乱码问题

    在web开发过程中,乱码问题是一个常见的困扰,尤其是在处理文本数据时。乱码现象通常发生在字符编码不一致或处理不当的场景下。本篇将详细探讨这个问题,以及如何通过理解和运用正确的字符编码来解决它。 首先,...

Global site tag (gtag.js) - Google Analytics