Web开发中常见的“乱码”

by.郑, 佳润 2017-7-6

问题来源:

在微信公众号开发指定回复消息为文本格式的时候,尝试了几种换行方式都不行,最终了解即XML的换行应使用:



是字符实体编号(16进制),可以用于处理XML中文本的换行。

对应的正确代码在第9行(部分文字有修改):

<xml>
  <ToUserName><![CDATA[<%= toUserName %>]]></ToUserName>
  <FromUserName><![CDATA[<%= fromUserName %>]]></FromUserName>
  <CreateTime><% createTime %></CreateTime>
    <MsgType><![CDATA[<%= msgType %>]]></MsgType>
    <% if (msgType === 'text') { if(content!=="zs") { %>
      <Content><![CDATA[<%= content %>]]></Content>
      <% } else { %>
      <Content>欢迎来到报名图书馆暑假工!&#x00A;&#x00A;&#x00A;报名步骤:&#x00A;&#x00A;①将招聘推文转发至朋友圈或者40人以上的群,让更多同学了解本招聘。为招聘方宣传以找到更多优质学生员工。&#x00A;&#x00A;&lt;a href=&quot;http://a.xiumi.us/board/v5/29Ndm/47380885&quot;&gt;点此进入招聘推文&lt;/a&gt;&#x00A;&#x00A;②回复你的资料:报名+姓名+电话号码+深圳哪个区+可上班时间&#x00A;&#x00A;&#x00A;</Content>
      <% }} else if (msgType === 'zs') { %>
      <Content>&lt;a href=&quot;http://www.baidu.com/?k381740148&quot;&gt;ddwadwada&lt;/a&gt;</Content>
      <% } else if (msgType === 'image') { %>
        <Image>
          <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
      </Image>
  ...
</xml>

由这个问题,我们想到web开发中还有一些类似的“乱码”,这些乱码又有哪些规律呢?

字符实体

字符实体是XML和HTML中的字符编码方式,也就是上面事例中提到的,格式为:

& + 实体名称 + ;
& + (# + unicode编码) + ;

实体名称一般是有意义的词,方便大家记忆,比如小于号<的实体名称是lt,也就是less than的缩写。只有部分符号是有实体名称的,使用unicode编码是更通用的写法。

像文字类一般不会采用这种编码方式,主要用于在HTML或XML文档中输出一些保留字符和空格,比如我想在HTML中展示一段html代码就需要使用字符实体

比如我们要展示`<p>情深深雨蒙蒙</p>` 以下两种表示是等效的
​
<pre>
  &lt;p&gt;情深深雨蒙蒙&lt;&#47;p&gt;
  &#60;p&#62;情深深雨蒙蒙&#60;&#47;p&#62;
</pre>

总而言之,字符实体是HTML和XML中的编码方式,比如在HTML文档中写入:&#x6211;,那么最终页面上看到的是这个汉字。

unicode字符

编程语言中的unicode字符的格式为:

\u + 16进制unicode编码

绝大多数编程语言,包括CSS中都支持unicode字符,不过HTML和XML是不支持的。那么什么时候使用unicode字符呢?一般来说有两种场景:

  1. 避免文件保存时采用不同编码导致的乱码,因为\u已经声明了是unicode。
  2. 正则匹配中的一些应用:Unicode编码及在正则表达式中的使用

在JS中可以使用charCodeAt()获取字符串的10进制unicode编码

URL编码

类似%E6%88%91这样的,叫做URL编码,在链接的参数里非常常见

网络标准RFC 1738做了硬性规定:

“只有字母和数字[0-9a-zA-Z]、一些特殊符号”$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

所以像汉字,空格这些都必须经过转码。上面讲的unicode字符,字符实体用的都是unicode编号,而URL编码用的则是utf-8, 规则是将utf-8编码每隔两个字符加一个%

UTF 是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。unicode和utf-8并不是同一种东西,但是又存在着联系:unicode是信源编码,对字符集数字化; utf-8,utf-16这些是信道编码,为更好的存储和传输。

简单说,unicode就是一组数字,每一个数字对应一个字符。utf-8就是对字符的传输和保存时的规则。比如说“我”这个字,unicode码(16进制)是6211,utf-8是E68891, 那么对应的URL编码就是%E6%88%91;

{
  Unicode编码: 0x6211,
  UTF8编码: E68891,
  UTF16编码: FEFF6211,
  UTF32编码: 0000FEFF00006211
  URL编码: %E6%88%91
}

更多细节可以参考《阮一峰:关于URL编码》

总结

Web开发中常见的几种乱码包括:Unicode字符、字符实体、URL编码。如以下情况都表示“我”

Unicode字符: \u6211
字符实体编号(16进制):&#x6211;
字符实体编号(10进制):&#25105;
URL编码:%E6%88%91

这些编码规则的本质都是一些特殊符号 + Unicode编码 所组成。

参考资料:

赞一个(15)