关于字符集和Unicode的相关知识[译](4)
作者:Joel Spolsky 发布时间:2010-03-13 14:17:00
编码
要存储,编码的概念当然就被引入进来。
Unicode最早的编码想法,就是把每一个码点(code point)都存储在两个字节中,这也就导致了大多数人的误解。于是Hello就变成了:
这样对吗?如下如何?
技术上说,我相信这样是可以的。事实上,早期的实现者们的确想把Unicode的码点(code point)按照大端或小端两种方式存储,这样至少已经有两种存储Unicode的方法了。于是人们就必须使用FE FF作为每一个Unicode字符串的开头,我们称这个为Unicode Byte Order Mark。如果你互换了你的高位与低位,就变成了FF FE,这样读取这个字符串的程序就知道后面字节也需要互换了。可惜,不是每一个Unicode字符串都有字节序标记。
现在,看起来好像问题已经解决了,可是这帮程序员仍在抱怨。"看看这些零!"他们会这样说,因为他们是美国人,他们只看不会码点不会超过U+00FF的英文字母。同时他们也是California的嬉皮士,他们想节省一点。如果他们是得克萨斯人,可能他们就不会介意两倍的字节数。但是这样California节俭的人却无法忍受字符串所占空间翻倍。而且现在大堆的文档使用的是ANSI和DBCS字符集,谁去转换它们?于是这帮人选择忽略Unicode,继续自己的路,这显然让事情变得更糟。
于是非常聪明的UTF-8的概念被引入了。UTF-8是另一个系统,用来存储字符串所对应的Unicode的码点 (code points)-即那些神奇的U+数字组合,在内存中,而且存储的最小单元是8比特的字节。在UTF-8中,0-127之间的码字都使用一个字节来存储,超过128的码字使用2,3甚至6个字节来存储。
这显然有非常好的效果,因为英文的文本使用UTF-8存储的形式完全与ASCII一样了,所以美国人压根不会注意到发生了什么变化。举个例子,Hello -- U+0048 U+0065 U+006C U+006C U+006C U+006F,将会被存储为48 65 6C 6C 6F,这与ASCII、与ANSI标准、与所有这个星球上的OEM字符集显然都是一样的。现在,如果你需要使用希腊字母,你可以用几个字节来存储一个码字,美国人永远都不会注意到。(干吗得美国人注意,无语,美国人写的文章...)
到现在我已经告诉了你三种Unicode的编码方式,传统的使用两个字节存储的称之为UCS-2或者UTF-16,而且你必须判断空间是大端的UCS-2还是小端的UCS-2。新的UTF-8标准显然更流行,如果你恰巧有专门面向英文的程序,显然这些程序不需要知道UTF-8的存在依然可以工作地很好。
事实上,还有其它若干对Unicode编码的方法。比如有个叫UTF-7,和UTF-8差不多,但是保证字节的最高位总是0,这样如果你的字符不得不经过一些严格的邮件系统时(这些系统认为7个比特完全够用了),就不会有信息丢失。还有一个UCS-4,使用4个字节来存储每个码点(code point),好处是每个码点都使用相同的字节数来存储,可惜这次就算是得克萨斯人也不愿意了,因为这个方法实在太浪费了。
现在的情况变成了你思考事情时所使用的基本单元--柏拉图式的字母已经被Unicode的码点完全表示了。这些码点也可以完全使用其它旧的编码体系。比如,你可以把 Hello对应的Unicode码点串(U+0048 U+0065 U+006C U+006C U+006F)用ASCII、OEM Greek、Hebrew ANSI或其它上百个编码体系来编码,不过需要注意一点,有些字母会无法显示。如果你要表示的Unicode码点在你使用的编码体系中压根没有对应的字符,那么你可能会得到一个小问号"?",或者得到一个"�"。
许多传统的编码体系仅仅能编码Unicode码点中的一部分,其余全部会被显示为问号。比较流行的英文编码体系有Windows-1252(Windows 9x中的西欧语言标准)和ISO-8859-1,还有aka Latin-1。但是如果想用这些编码体系来编码俄语或者希伯来语就只能得到一串问号了。UTF 7,8,16,和32都可以完全正确编码Unicode中的所 * 点。


猜你喜欢
- 定义函数:CREATE FUNCTION [dbo].[GetAge] ( @BirthDay nvarchar(2
- 本文实例为大家分享了python3实现ftp服务功能的具体代码,供大家参考,具体内容如下功能介绍:可执行的命令:lspwdcd put rm
- 系列教程MySQL系列之开篇 MySQL关系型数据库基础概念 MySQL系列之一 MariaDB-server安装 MySQL系列之二 多实
- 翻译:用法:zeros(shape, dtype=float, order='C')返回:返回来一个给定形状和类型的用0填充
- 今天偶然看到“一个有将近两年的div + CSS 开发经验和历史,曾经是Web标准绝对拥趸的同志”在自己的blog上发表放弃div+css的
- 看到这个先思考,自己怎么输出他?为什么它有颜色?特殊符号去哪找?特殊符号在符号大全找 符号大全http://www.fhdq.net/任务1
- 版本:ant design vue 3.2.4场景:使用Image图片组件预览功能需求:自定义预览遮罩层及预览图片的样式;不得影响到其他页面
- 在我们的日常工作自动化测试当中,几乎超过一半的功能都需要利用定时的任务来推动触发,例如在我们项目中有一个定时监控模块,根据自己设置的频率定时
- 本文介绍了使用Application来统计访问网站的在线人数的方法,并介绍了使用Application时应该注意的事项。首先讲明白,用ASP
- 有时候我们的数据是按某个频率收集的,比如每日、每月、每15分钟,那么我们怎么产生对应频率的索引呢?pandas中的date_range可用于
- 一、VSCode 创建Django 工程VSCode 官方: https://code.visualstudio.com1 mysite(项
- 本文实例讲述了C#简单访问SQLite数据库的方法。分享给大家供大家参考,具体如下:下载最新版SQLite(http://www.sqlit
- 继上一篇中间表的数据是动态的,图表展示的数据才比较准确。这里用到一个新的模块Djcelery,安装配置步骤如下:1.安装redis==2.1
- 1. 基础缩略图给a标签添加类class="thumbnail"如下:<div class="
- 0.先给大家看看效果:1.创建一个index.html文件<!DOCTYPE html><html lang="
- 升级pippip版本必须升级到20.0.4版本才能应用;方法一、在pycharm中对pip进行升级;方法二、通过命令进行升级python3.
- //方法1:$ip = $_SERVER["REMOTE_ADDR"];echo $ip;//方法2:$user_IP
- 1.背景一直苦恼于本地机器和服务器上都要配置一些机器学习方面的环境,今天花了点时间研究了下Jupter notebook远程访问服务器,所以
- 我们开发数据库应用时,常常需要用到模糊查询。如果同一个条件需要匹配很多字段怎么办呢?通常,程序员会每个字段都在SQL中“field like
- window.location.pathname 比如: /windows/location/page.html 我想得到“windows”