首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

基于UTF-8Web应用程序

UTF-8 Web Applications

当我们提出让一个应用程序使用UTF-8时是什么意思? 它其实意味着几件事,这些事都相当简单,但在整个开发过程中都必须铭记在心。

输出处理

Handling Output

我们希望所有的输出页面都要用UTF-8提供。为此,我们需要使用支持Unicode的代码编辑器来建立标记模板。在保存档案时,还得要求它们必须被储存成UTF-8格式。在大多数情况下,如果你曾经使用Latin-1(更为正式的名称是ISO-8859-1),那一切都不会发生太大的变化。其实什么都不会改变,除非你使用了一些高重音字母。模板编码成UTF-8后, 所有要做的就是告诉浏览器你所提供的页面是如何编码的。 您可以使用content-type标头的charset属性:

Content-Type: text/html; charset=utf-8

也许你还没有留意到,charset这个属性名字很奇怪。它既表示字符集也表示编码,虽然大多情况下表示编码。那么,我们应该如何和页面一起输出这个标头? 有几个方法,它们中几个或者全部的组合,足以让大多数应用程序工作得很好。要发送一个正常的HTTP 标头,可以通过应用程序的代码或通过服务器配置来完成。如果您使用Apache,那么你可以添加addcharset指令到主要的httpd.conf文件或者特定的. htaccess的文件中,从而为所

有给定的扩展文档设置charset:

AddCharset UTF-8 .php

在PHP中,你可以使用简单的header()函数来输出HTTP标头。为了输出特定的UTF-8标头,可以使用以下的代码:

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

这种做法有个小缺点,你必须明确地输出主要内容类型(在本例中是text/html),而不是让服务器根据用户的浏览器引擎自动确定类型。这在选择发送类型是text/html或者application/xhtml+xml时会带来某些问题(后者在技术上是正确的,但导致Netscape 4和有些版本的Internet Explorer 6提示你下载页面)。

除了以正常的HTTP请求的一部分送出标头外,也可以将标头通过meta标签置于HTML内容中。这可以很方便地添加到你的页面中,只需要把以下的HTML放置在目标的head标签中:

<meta http-equiv="Content-Type" content=

"text/html; charset=UTF-8">

使用meta标签比使用正常的标头的好处在于如果有人保存了页面,那么只会保存页面内容而不包括标头,这时编码将依然存在于meta标签中。有一些重要的原因让我们需要发送标头而不仅仅是使用meta标签。首先,你的网站服务器可能已经发送了不正确的编码,将覆盖http-equiv版本的编码,您需要使用正确的标头来覆盖或者替换错误的编码。其次,大多数浏览器遇到meta标签之后,都需要重新解析文件,因为可能有已经被按错误编码解析的文本。这样做会延误页面绘制,或者由于用户的浏览器而完全被忽视。不言而喻,最好的情况是HTTP 标头中的编码和meta标签中的相一致,否则,最后的页面绘制结果有些难以预测。

要用UTF-8提供HTML以外的其他文件时,同样的规则也是适用的。对于XML文件和订阅地址,你可以再次使用HTTP标头,但使用不同的主要内容类型content-type:

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

和HTML不同,XML无法包含任意HTTP 标头到文档中。幸好,XML直接支持编码(和charset相比,这次的命名比较合适)作为XML的序言的一部分。要说明你的XML文件编码为UTF-8,你要做的只是使用这样的序言:

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

输入处理

Handling Input

通过Form字段提交给应用程序的输入,将会自动使用相应页面被派发时使用的字符集和编码。也就是说, 如果你的所有页面都是UTF-8编码,那么你所有的输入也将使用UTF-8编码。但是,在这个美妙的乌托邦世界里,也有一些需要注意的。如果有人在另一个站点上建立了一个Form,提交数据到你应用程序中的一个URL。那么输入将采用数据产生处的字符集和编码。很老的浏览器都总是用一种特定编码发送数据,而不理睬你的要求。用户可能建立应用程序,而这些应用意外的使用错误的编码来投递数据到你的应用程序。而另一些用户,却可能创建有意采用你没有预料到的编码来投递数据的应用程序。所有这些输入将导致同样的后果。所有进入的数据在能够安全使用之前,都需要进行过滤。在下一章我们会讨论这个问题的更多细节。

PHP中使用UTF-8

Using UTF-8 with PHP

UTF-8是一个面向字节的编码,它有这样的附带效果:假如你不想和字符串内容打交道,那你可以通过使用任意的binary安全(二进制安全,意味着我们可以存储任何字节的值到一个“串”,而且总是能得到完全相同的字节)的系统传送它。这意味着PHP 4和PHP 5可以轻易地支持一个Unicode应用,而无需将任何字符集或编码支持内建到语言中。如果我们所有要做的就是使用UTF-8接收数据编码、储存,然后直接地输出,我们将永远不需要做比拷贝大块字节更多的事。但有一些可能需要进行的操作,没有某种Unicode支持是不可能实现的。比如,你不能够执行正常的substr()(substring)的操作。substr()是一个基于字节的操作,而且你不能在字节边界安全地对UTF-8编码的字符串任意进行分段。 比如说,如果你切断一个UTF-8编码的字符串的头3个字节,切入点可能正好在一个字符序列的中部,而留下的就是一个不完整的字符。如果这些让你很想迁移至固定宽度编码,比如UCS2,那么值得注意的是,你还是不能随意地分段 Unicode字符串,即使是在字符边界(在一个固定宽度编码,可以很容易地找到)。因为Unicode允许组合字符以区分和组成其他标记,两个码点之间的分割可能导致字符串末端的字符缺少了它的重音符号,或者让字符串开头的重音符号变得形单影孤(或者两倍长度的组合标记带来的奇怪的附加效果,这些太让人困惑了,在这里不予考虑)。

任何依赖substring操作的函数也因此不能被安全地使用。PHP就包含像wordwrap()和chunk_split()这样的函数。

在PHP中,Unicode的substring支持来自于mbstring(多字节string)扩展,它并没有和默认的PHP可执行文件打包在一起。一旦安装好了这个扩展,它会给你提供可选的字符串操作函数,如mb_substr()替代了substr()等。实际上,mbstring扩展包含了对现有的字符串操作函数的多载,所以只要简单地调用常规的函数,实际上就会自动调用mb_...()函数。可是多载也会带来问题,这让它变得没有实际价值。如果你在某处使用任何字符串操作函数处理二进制数据(这里是指真正的二进制数据,而不是被当成二进制的文本数据),而你又多载了字符串操作函数,那就会破坏二进制处理代码。因此,在有需要的地方明确调用多字节函数通常是最安全的做法。

除了要担心UTF-8编码的字符串的操作,还有一个需要在语言级别提供的功能,即验证数据有效性的能力。并不是所有的字节流都是有效的UTF-8。在第5章我们会更加深入地探讨这个问题。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论