资讯专栏INFORMATION COLUMN

Combining Character

Meils / 1744人阅读

摘要:今天要讨论的是关于字符编码的一些问题,源自一次项目周会,因网络上没有相关文章,现在刚好能总结一下。为招聘方宣传以找到更多优质学生员工。延伸阅读阮一峰字符编码笔记阮一峰关于编码阮一峰与字符集与字符编码知乎和有什么区别中的坑

第一次写segmentfault,欢迎大家提意见以便改进。

今天要讨论的是关于字符编码的一些问题,源自一次项目周会,因网络上没有相关文章,现在刚好能总结一下。

1. 首先来看几张有意思的现象:

(1) 下面这幅图中出现一些“叠起来”的字体,来自微信公众号“麦当劳”于2017年6月28日的推送,感兴趣的同学可以去看看。

比如第一个“叠起来”的字,分别由以下两个字体组成,其它的“特技字体”也一样。

(2) 再看下面这个字,我把它复制粘贴到这:
小⃠

在Chrome浏览器看到的可能是下面这样:

在iPhone微信和Safari等平台或浏览器上看到的可能是:

在某些Android微信上看到的可能是:

你可以复制这个网站地址,或者可以复制字符串"小⃠"到不同平台上观察显示的效果。

(3) 连续打两个字符,如:

Chrome浏览器显示:

Sarafi浏览器显示:

在写这篇blog的时候,我也很苦恼,怎么写出这个"?"符号,因为经常会和前面的一个字符“叠起来”,会造成误解。

(4) 复制“小⃠”到Chrome地址栏时,显示倒是“正常”:

但是,上图是地址栏获得焦点时的情况,如果此时失去焦点会发生如下情况:

2. 分析

(1) 不妨先用内置的encodeURIComponent()decodeURIComponent()探个究竟。

总的来说,这个“叠起来”的字符解码之后是这个结果(为了便于查看,这里用Safari进行测试):

至于%E2%83%A0,我用Chrome控制台输出,因为在Safari下编辑器处理这段编码的结果会把写注释的"/"叠上,如图:

(2) 翻阅了许多资料终于在Wikipedia找到相关内容,https://en.wikipedia.org/wiki...

其中讲到一些背景因素,以及一些奇葩的组合类型:

In digital typography, combining characters are characters that are intended to modify other characters. The most common combining characters in the Latin script are the combining diacritical marks (including combining accents).

Unicode also contains many precomposed characters, so that in many cases it is possible to use both combining diacritics and precomposed characters, at the user"s or application"s choice. This leads to a requirement to perform Unicode normalization before comparing two Unicode strings and to carefully design encoding converters to correctly map all of the valid ways to represent a character in Unicode to a legacy encoding to avoid data loss.

In Unicode, the main block of combining diacritics for European languages and the International Phonetic Alphabet is U+0300–U+036F. Combining diacritical marks are also present in many other blocks of Unicode characters. In Unicode, diacritics are always added after the main character, so it is possible to add several diacritics to the same character, although as of 2010, few applications support correct rendering of such combinations.

3. 看到这也大致了解了 Combining Character,不妨再看看Web开发中常见的乱码:

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

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

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


  ]]>
  ]]>
  <% createTime %>
    ]]>
    <% if (msgType === "text") { if(content!=="zs") { %>
      ]]>
      <% } else { %>
      欢迎来到报名图书馆暑假工!


报名步骤:

①将招聘推文转发至朋友圈或者40人以上的群,让更多同学了解本招聘。为招聘方宣传以找到更多优质学生员工。

→点此进入招聘推文

②回复你的资料:报名+姓名+电话号码+深圳哪个区+可上班时间



      <% }} else if (msgType === "zs") { %>
      ddwadwada
      <% } else if (msgType === "image") { %>
        
          ]]>
      
  ...

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

(1) 字符实体

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

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

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

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

比如我们要展示

情深深雨蒙蒙

以下两种表示是等效的:

  

情深深雨蒙蒙</p>

情深深雨蒙蒙</p>

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

(2) unicode字符

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

u + 16进制unicode编码

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

避免文件保存时采用不同编码导致的乱码,因为u已经声明了是unicode。

正则匹配中的一些应用:Unicode编码及在正则表达式中的使用

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

(3) 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
}

(4) 本段小结:

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

Unicode字符: u6211
字符实体编号(16进制):我
字符实体编号(10进制):我
URL编码:%E6%88%91

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

4. 总结

从【1】中展示的,各种奇怪现象我们找到原因和资料是Combining Character以及编码相关问题,其次我们也拓展了一下Web开发中常见的一些”乱码”以及相关的技术背景。

欢迎大家指正或提意见以便改进。

5. 延伸阅读

《阮一峰:字符编码笔记》

《阮一峰:关于URL编码》

《阮一峰:Unicode与JavaScript》

字符集与字符编码

知乎:unicode和utf-8有什么区别

javascript中unicode的坑

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90139.html

相关文章

  • 你真的会字符串反转、计算字符串长度么?

    摘要:你真的会字符串反转计算字符串长度么字符串编码问题一个常见的问题如何将字符串反转一个常见的解答再如,如何得到一个字符串的长度答这些答案都不是完全正确,或者说并不是对于所有的字符都是适用的,例如这其中的原因涉及到了的字符串编码。 你真的会字符串反转、计算字符串长度么? Javascript 字符串编码 问题 一个常见的问题:如何将字符串反转? 一个常见的解答: abcd.split().r...

    1fe1se 评论0 收藏0
  • JAVA中单元测试的常用方式

    摘要:中常用的单元测试工具是老牌测试框架了,也是目前引用最广泛的一个框架。可以使用适当的单元测试方式,比如可以提供一个测试接口,利用的热部署功能实现不重启及时修改代码。 什么是单元测试 单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;...

    Ryan_Li 评论0 收藏0
  • Python学习之路23-文本和字节序列

    摘要:字符编码表,码位码元将编码字符集中的码位转换成有限比特长度的整型值的序列。字符编码方案,码元序列化也称为常说的序列化。每个字节里的二进制数就是字节序列。另一个情况则是压缩字节序列的值,如或进程长度编码等无损压缩技术。 《流畅的Python》笔记。本篇主要讲述不同编码之间的转换问题,比较繁杂,如果平时处理文本不多,或者语言比较单一,没有多语言文本处理的需求,则可以略过此篇。 1. 前言 ...

    anRui 评论0 收藏0
  • ES6字符串

    摘要:提供的方法,可在字符串比较之前正规化,规避这种错误。过去判断数组或字符串中包含某一元素的时候需要用到方法,现在数组或字符串都能使用方法来判断是否包含某一元素。下面代码生成位的数值字符串。另一个用途是提示字符串格式。 1. 字符串的遍历 ES6字符串增加了遍历器接口,for-of 语法,相比传统for(let i=0;.....)来循环字符串,for-of循环可以识别大于0xFFFF的码...

    cppprimer 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<