??xml version="1.0" encoding="utf-8" standalone="yes"?> q是一程序员写给E序员的味ȝ。所谓趣x指可以比较轻村֜了解一些原来不清楚的概念,增进知识Q类g打RPG游戏的升U。整理这文章的动机是两个问题: 使用WindowsC本的“另存?#8221;Q可以在GBK、Unicode、Unicode big endian和UTF-8q几U编码方式间怺转换。同htxt文gQWindows是怎样识别~码方式的呢Q?/p>
我很早前发现Unicode、Unicode big endian和UTF-8~码的txt文g的开头会多出几个字节Q分别是FF、FEQUnicodeQ?FE、FFQUnicode big endianQ?EF、BB、BFQUTF-8Q。但q些标记是基于什么标准呢Q?/p>
查了查相兌料,ȝ这些问题弄清楚了,带也了解了一些Unicode的细节。写成一文章,送给有过cM疑问的朋友。本文在写作时尽量做到通俗易懂Q但要求读者知道什么是字节Q什么是十六q制?/p>
big endian和little endian是CPU处理多字节数的不同方式。例?#8220;?#8221;字的Unicode~码?C49。那么写到文仉ӞI竟是将6C写在前面Q还是将49写在前面Q如果将6C写在前面Q就是big endian。如果将49写在前面Q就是little endian?/p>
“endian”q个词出自《格列佛(jng)游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开q是从小?Little-Endian)敲开Q由此曾发生q六ơ叛乱,一个皇帝送了命,另一个丢了王位?/p>
我们一般将endian译?#8220;字节?#8221;Q将big endian和little endianUC“大尾”?#8220;尾”?/p>
字符必须~码后才能被计算机处理。计机使用的缺省编码方式就是计机的内码。早期的计算Z?位的ASCII~码Qؓ了处理汉字,E序员设计了用于体中文的GB2312和用于繁体中文的big5?/p>
GB2312(1980q?一共收录了7445个字W,包括6763个汉字和682个其它符受汉字区的内码范围高字节从B0-F7Q低字节从A1-FEQ占用的码位?2*94=6768。其中有5个空位是D7FA-D7FE?/p>
GB2312支持的汉字太?995q的汉字扩展规范GBK1.0收录?1886个符P它分为汉字区和图形符号区。汉字区包括21003个字W?/p>
从ASCII、GB2312到GBKQ这些编码方法是向下兼容的,卛_一个字W在q些Ҏ(gu)中L有相同的~码Q后面的标准支持更多的字W。在q些~码中,英文和中文可以统一地处理。区分中文编码的Ҏ(gu)是高字节的最高位不ؓ0。按照程序员的称|GB2312、GBK都属于双字节字符?(DBCS)?/p>
2000q的GB18030是取代GBK1.0的正式国家标准。该标准收录?7484个汉字,同时q收录了藏文、蒙文、维向ְ文等主要的少数民族文字。从汉字字汇上说QGB18030在GB13000.1?0902个汉字的基础上增加了CJK扩展A?582个汉字(Unicode?x3400-0x4db5Q,一共收录了27484个汉字?/p>
CJK是中日韩的意思。UnicodeZ节省码位Q将中日韩三国语a中的文字l一~码。GB13000.1是ISO/IEC 10646-1的中文版Q相当于Unicode 1.1?/p>
GB18030的编码采用单字节、双字节?字节Ҏ(gu)。其中单字节、双字节和GBK是完全兼容的?字节~码的码位就是收录了CJK扩展A?582个汉字?例如QUCS?x3400在GB18030中的~码应该?139EF30QUCS?x3401在GB18030中的~码应该?139EF31?/p>
微Y提供了GB18030的升U包Q但q个升包只是提供了一套支持CJK扩展A?582个汉字的新字体:新宋?18030Qƈ不改变内码。Windows 的内码仍然是GBK?/p>
q里q有一些细节: GB2312的原文还是区位码Q从Z码到内码Q需要在高字节和低字节上分别加上A0?/p>
对于M字符~码Q编码单元的序是由~码Ҏ(gu)指定的,与endian无关。例如GBK的编码单元是字节Q用两个字节表示一个汉字?q两个字节的序是固定的Q不受CPU字节序的影响。UTF-16的编码单元是wordQ双字节Q,word之间的顺序是~码Ҏ(gu)指定的,word内部的字节排列才会受到endian的媄响。后面还会介lUTF-16?/p>
GB2312的两个字节的最高位都是1。但W合q个条g的码位只?28*128=16384个。所以GBK和GB18030的低字节最高位都可能不?。不q这不媄响DBCS字符的解析Q在dDBCS字符时Q只要遇到高位ؓ1的字节,可以将下两个字节作Z个双字节~码Q而不用管低字节的高位是什么?/p>
前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容Q更准确地说Q是与ISO-8859-1兼容Q,与GB码不兼容。例?#8220;?#8221;字的Unicode~码?C49Q而GB码是BABA?/p>
Unicode也是一U字W编码方法,不过它是由国际组l设计,可以容纳全世界所有语a文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"Q简UCؓUCS。UCS可以看作?Unicode Character Set"的羃写?/p>
Ҏ(gu)l基癄全书(http://zh.wikipedia.org/wiki/)的记载:历史上存在两个试囄立设计Unicode的组l,卛_际标准化l织QISOQ和一个Y件制造商的协会(unicode.orgQ。ISO开发了ISO 10646目QUnicode协会开发了Unicode目?/p>
?991q前后,双方都认识到世界不需要两个不兼容的字W集。于是它们开始合q双方的工作成果Qƈ为创立一个单一~码表而协同工作。从Unicode2.0开始,Unicode目采用了与ISO 10646-1相同的字库和字码?/p>
目前两个目仍都存在Qƈ独立地公布各自的标准。Unicode协会现在的最新版本是2005q的Unicode 4.1.0。ISO的最新标准是ISO 10646-3:2003?/p>
UCS只是规定如何~码Qƈ没有规定如何传输、保存这个编码。例?#8220;?#8221;字的UCS~码?C49Q我可以?个ascii数字来传输、保存这个编码;也可以用utf-8~码:3个连l的字节E6 B1 89来表C它。关键在于通信双方都要认可。UTF-8、UTF-7、UTF-16都是被广泛接受的Ҏ(gu)。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。UTF?#8220;UCS Transformation Format”的羃写?/p>
IETF的RFC2781和RFC3629以RFC的一贯风|清晰、明快又不失严}地描qCUTF-16和UTF-8的编码方法。我LC得IETF是Internet Engineering Task Force的羃写。但IETF负责l护的RFC是Internet上一切规范的基础?/p>
目前Windows的内核已l支持Unicode字符集,q样在内怸可以支持全世界所有的语言文字。但是由于现有的大量E序和文档都采用了某U特定语a的编码,例如GBKQWindows不可能不支持现有的编码,而全部改用Unicode?/p>
Windows使用代码?code page)来适应各个国家和地区。code page可以被理解ؓ前面提到的内码。GBK对应的code page是CP936?/p>
微Y也ؓGB18030定义了code pageQCP54936。但是由于GB18030有一部分4字节~码Q而Windows的代码页只支持单字节和双字节~码Q所以这个code page是无法真正用的?/p>
UCS有两U格式:UCS-2和UCS-4。顾名思义QUCS-2是用两个字节编码,UCS-4是?个字节(实际上只用了31位,最高位必须?Q编码。下面让我们做一些简单的数学游戏Q?/p>
UCS-2?^16=65536个码位,UCS-4?^31=2147483648个码位?/p>
UCS-4Ҏ(gu)最高位?的最高字节分?^7=128个group。每个group再根据次高字节分?56个plane。每个planeҎ(gu)W?个字节分?56?(rows)Q每行包?56个cells。当然同一行的cells只是最后一个字节不同,其余都相同?/p>
group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节ؓ0的码位被UCBMP?/p>
UCS-4的BMPL前面的两个零字节得CUCS-2。在UCS-2的两个字节前加上两个零字节,得CUCS-4的BMP。而目前的UCS-4规范中还没有M字符被分配在BMP之外?/p>
UTF-8是?位ؓ单元对UCSq行~码。从UCS-2到UTF-8的编码方式如下: 例如“?#8221;字的Unicode~码?C49?C49?800-FFFF之间Q所以肯定要?字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是Q?110 110001 001001Q?用这个比Ҏ(gu)依次代替模板中的xQ得刎ͼ11100110 10110001 10001001Q即E6 B1 89?/p>
读者可以用C本测试一下我们的~码是否正确。需要注意,UltraEdit在打开utf-8~码的文本文件时会自动{换ؓUTF-16Q可能生淆。你可以在设|中xq个选项。更好的工具是Hex Workshop?/p>
UTF-16?6位ؓ单元对UCSq行~码。对于小?x10000的UCS码,UTF-16~码q于UCS码对应的16位无W号整数。对于不于0x10000的UCS码,定义了一个算法。不q由于实际用的UCS2Q或者UCS4的BMP必然于0x10000Q所以就目前而言Q可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题?/p>
UTF-8以字节ؓ~码单元Q没有字节序的问题。UTF-16以两个字节ؓ~码单元Q在解释一个UTF-16文本前,首先要弄清楚每个~码单元的字节序。例?#8220;?#8221;的Unicode~码?94EQ?#8220;?#8221;的Unicode~码?E59。如果我们收到UTF-16字节?#8220;594E”Q那么这?#8220;?#8221;q是“?#8221;Q?/p>
Unicode规范中推荐的标记字节序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法: 在UCS~码中有一个叫?ZERO WIDTH NO-BREAK SPACE"的字W,它的~码是FEFF。而FFFE在UCS中是不存在的字符Q所以不应该出现在实际传输中。UCS规范我们在传输字节流前,先传输字W?ZERO WIDTH NO-BREAK SPACE"?/p>
q样如果接收者收到FEFFQ就表明q个字节是Big-Endian的;如果收到FFFEQ就表明q个字节是Little-Endian的。因此字W?ZERO WIDTH NO-BREAK SPACE"又被UCBOM?/p>
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字W?ZERO WIDTH NO-BREAK SPACE"的UTF-8~码是EF BB BFQ读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收CEF BB BF开头的字节,q道这是UTF-8~码了?/p>
Windows是使用BOM来标记文本文件的~码方式的?/p>
本文主要参考的资料?"Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)?/p>
我还找了两篇看上M错的资料Q不q因为我开始的疑问都找C{案Q所以就没有看: 我写qUTF-8、UCS-2、GBK怺转换的Y件包Q包括用Windows API和不使用Windows API的版本。以后有旉的话Q我会整理一下放到我的个Z上(http://fmddlmyy.home4u.china.com)?/p>
我是x楚所有问题后才开始写q篇文章的,原以Z会儿p写好。没惛_考虑措辞和查证细节花费了很长旉Q竟然从下午1:30写到9:00。希望有读者能从中受益?/p>
有的朋友Ҏ(gu)章中q句话还有疑问: 我再详细解释一下: “GB2312的原?#8221;是指国家1980q的一个标准《中华h民共和国国家标准 信息交换用汉字编码字W集 基本?GB 2312-80》。这个标准用两个数来~码汉字和中文符受第一个数UCؓ“?#8221;Q第二个数称?#8220;?#8221;。所以也UCؓZ码?-9区是中文W号Q?6-55区是一U汉字,56-87区是二汉字。现在Windows也还有区位输入法Q例如输?601得到“?#8221;。(q个Z输入法可以自动识?6q制的GB2312?0q制的区位码Q也是说输入B0A1同样会得?#8220;?#8221;。) 内码是指操作pȝ内部的字W编码。早期操作系l的内码是与语言相关的。现在的Windows在系l内部支持UnicodeQ然后用代码适应各种语言Q?#8220;内码”的概念就比较模糊了。微软一般将~省代码|定的~码说成是内码?/p>
内码q个词汇Qƈ没有什么官方的定义Q代码页也只是微软这个公司的叫法。作为程序员Q我们只要知道它们是什么东西,没有必要q多地考证q些名词?/p>
Windows中有~省代码늚概念Q即~省用什么编码来解释字符。例如Windows的记事本打开了一个文本文Ӟ里面的内Ҏ(gu)字节:BA、BA、D7、D6。Windows应该L么解释它呢Q?/p>
是按照Unicode~码解释、还是按照GBK解释、还是按照BIG5解释Q还是按照ISO8859-1去解释?如果按GBK去解释,׃得到“汉字”两个字。按照其它编码解释,可能找不到对应的字符Q也可能扑ֈ错误的字W。所?#8220;错误”是指与文本作者的本意不符Q这时就产生了ؕ码?/p>
{案是Windows按照当前的缺省代码页去解释文本文仉的字节流。缺省代码页可以通过控制面板的区域选项讄。记事本的另存ؓ中有一ANSIQ其实就是按照缺省代码页的编码方法保存?/p>
Windows的内码是UnicodeQ它在技术上可以同时支持多个代码c只要文件能说明自己使用什么编码,用户又安装了对应的代码页QWindowsp正确昄Q例如在HTML文g中就可以指定charset?/p>
有的HTML文g作者,特别是英文作者,认ؓ世界上所有h都用英文,在文件中不指定charset。如果他使用?x80-0xff之间的字W,中文Windows又按照缺省的GBK去解释,׃出现q。这时只要在q个html文g中加上指定charset的语句,例如Q?br><meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"> 再说Z码,啊的Z码是1601Q写?6q制?x10,0x01。这和计机q泛使用的ASCII~码冲突。ؓ了兼?0-7f的ASCII~码Q我们在Z码的高、低字节上分别加上A0。这?#8220;?#8221;的编码就成ؓB0A1。我们将加过两个A0的编码也UCؓGB2312~码Q虽然GB2312的原文根本没提到q一炏V? Unicode: ----------------------------------------------------------原文------------------------------------------------------------------------------------ ----------------------------------------------------------U正?---------------------------------------------------------------------------------- 国际标准 ISO 10646 定义?通用字符?(Universal Character Set, UCS). UCS 是所有其他字W集标准的一个超? 它保证与其他字符集是双向兼容? 是? 如果你将M文本字符串翻译到 UCS格式, 然后再翻译回原编? 你不会丢׃Q何信? UCS 包含了用于表达所有已知语a的字W? 不仅包括拉丁?希腊? 斯拉夫语,希伯来语,阿拉伯语,亚美g语和乔治亚语的描q? q包括中? 日文和韩文这L象Ş文字, 以及 q_? 片假? 孟加拉语, 旁遮普语果鲁I奇字符(Gurmukhi), 泰米语, ?埃纳徯(Kannada), Malayalam, 泰国? 老挝? 汉语拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他CC清的? 对于q没有加入的语言, ׃正在研究怎样在计机中最好地~码它们, 因而最l它们都被加入. q些语言包括 Tibetian, 高棉? Runic(古代北欧文字), 埃塞俄比亚语, 其他象Ş文字, 以及各种各样的印-Ƨ语pȝ语言, q包括挑选出来的艺术语言比如 Tengwar, Cirth ?克林贡语(Klingon). UCS q包括大量的囑Ş? 印刷用的, 数学用的和科学用的符? 包括所有由 TeX, Postscript, MS-DOSQMS-Windows, Macintosh, OCR 字体, 以及许多其他字处理和出版pȝ提供的字W? ISO 10646 定义了一?31 位的字符? 然? 在这巨大的编码空间中, q今为止只分配了?65534 个码?(0x0000 ?0xFFFD). q个 UCS ?16位子集称?基本多语a?(Basic Multilingual Plane, BMP). 被~码?16 ?BMP 以外的字W都属于非常Ҏ(gu)的字W?比如象Ş文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 来也许再也不会有字W被分配C 0x000000 ?0x10FFFF q个覆盖了超q?100 万个潜在的未来字W的 21 位的~码I间以外M. ISO 10646-1 标准W一ơ发表于 1993 q? 定义了字W集?BMP 中内容的架构. 定义 BMP 以外的字W编码的W二部分 ISO 10646-2 正在准备? 但也许要q好几年才能完成. 新的字符仍源源不断地加入?BMP ? 但已l存在的字符是稳定的且不会再改变? UCS 不仅l每个字W分配一个代? 而且赋予了一个正式的名字. 表示一?UCS ?Unicode 值的十六q制? 通常在前面加?"U+", p U+0041 代表字符"拉丁大写字母A". UCS 字符 U+0000 ?U+007F ?US-ASCII(ISO 646) 是一致的, U+0000 ?U+00FF ?ISO 8859-1(Latin-1) 也是一致的. ?U+E000 ?U+F8FF, 已经 BMP 以外的大范围的编码是为私用保留的. UCS里有些编码点分配l了 l合字符.它们cM于打字机上的无间隔重音键. 单个的组合字W不是一个完整的字符. 它是一个类g重音W或其他指示标记, 加在前一个字W后? 因? 重音W可以加在Q何字W后? 那些最重要的被加重的字W? p普通语a的正字法(orthographies of common languages)里用到的那种, ?UCS 里都有自q位置, 以确保同老的字符集的向后兼容? 既有自己的编码位|? 又可以表CZؓ一个普通字W跟随一个组合字W的被加重字W? 被称?预作字符(precomposed characters). UCS 里的预作字符是ؓ了同没有预作字符的旧~码, 比如 ISO 8859, 保持向后兼容性而设? l合字符机制允许在Q何字W后加上重音W或其他指示标记, q在U学W号中特别有? 比如数学方程式和国际x字母, 可能会需要在一个基本字W后l合上一个或多个指示标记. l合字符跟随着被修饰的字符. 比如, 徯中的元音变音字符 ("拉丁大写字母A 加上分音W?), 既可以表CZؓ UCS ?U+00C4 的预作字W? 也可以表C成一个普?"拉丁大写字母A" 跟着一?l合分音W?:U+0041 U+0308 q样的组? 当需要堆叠多个重音符, 或在一个基本字W的上面和下面都要加上组合标记时, 可以使用多个l合字符. 比如在泰国文? 一个基本字W最多可加上两个l合字符. 不是所有的pȝ都需要支持象l合字符q样?UCS 里所有的先进机制. 因此 ISO 10646 指定了下列三U实现? 历史? 有两个独立的, 创立单一字符集的试. 一个是国际标准化组l?ISO)?ISO 10646 目, 另一个是?一开始大多是国?多语a软g刉商l成的协会组l的 Unicode 目. q运的是, 1991q前? 两个目的参与者都认识? 世界不需要两个不同的单一字符? 它们合ƈ双方的工作成? qؓ创立一个单一~码表而协同工? 两个目仍都存在q独立地公布各自的标? ?Unicode 协会?ISO/IEC JTC1/SC2 都同意保?Unicode ?ISO 10646 标准的码表兼? q紧密地共同调整M未来的扩? Unicode 协会公布?Unicode 标准 严密地包含了 ISO 10646-1 实现U别3的基本多语言? 在两个标准里所有的字符都在相同的位|ƈ且有相同的名? Unicode 标准额外定义了许多与字符有关的语义符号学, 一般而言是对于实现高质量的印刷出版系l的更好的参? Unicode 详细说明了绘制某些语a(比如阿拉伯语)表达形式的算? 处理双向文字(比如拉丁与希伯来文合文?的算法和 排序与字W串比较 所需的算? 以及其他许多东西. 另一斚w, ISO 10646 标准, pqؓ人知?ISO 8859 标准一? 只不q是一个简单的字符集表. 它指定了一些与标准有关的术? 定义了一些编码的别名, q包括了规范说明, 指定了怎样使用 UCS q接其他 ISO 标准的实? 比如 ISO 6429 ?ISO 2022. q有一些与 ISO 紧密相关? 比如 ISO 14651 是关?UCS 字符串排序的. 考虑?Unicode 标准有一个易记的名字, 且在M好的书店里的 Addison-Wesley 里有, 只花?ISO 版本的一部? 且包括更多的辅助信息, 因而它成ؓ使用q泛得多的参考也׃ؓ奇了. 然? 一般认? 用于打印 ISO 10646-1 标准的字体在某些斚w的质量要高于用于打印 Unicode 2.0? 专业字体设计者L被徏议说要两个标准都实现, 但一些提供的样例字Ş有显著的区别. ISO 10646-1 标准同样使用四种不同的风格变体来昄表意文字如中? 日文和韩?(CJK), ?Unicode 2.0 的表里只有中文的变体. q导致了普遍的认?Unicode Ҏ(gu)本用h说是不可接收的传? 管是错误的. 首先 UCS ?Unicode 只是分配整数l字W的~码? 现在存在好几U将一串字W表CZؓ一串字节的Ҏ(gu). 最显而易见的两种Ҏ(gu)是将 Unicode 文本存储?2 ??4 个字节序列的? q两U方法的正式名称分别?UCS-2 ?UCS-4. 除非另外指定, 否则大多数的字节都是q样?Bigendian convention). 一?ASCII ?Latin-1 的文件{换成 UCS-2 只需单地在每?ASCII 字节前插?0x00. 如果要{换成 UCS-4, 则必d每个 ASCII 字节前插入三?0x00. ?Unix 下?UCS-2 (?UCS-4) 会导致非怸重的问题. 用这些编码的字符串会包含一些特D的字符, 比如 '\0' ?'/', 它们?文g名和其他 C 库函数参数里都有特别的含? 另外, 大多C?ASCII 文g?UNIX 下的工具, 如果不进行重大修Ҏ(gu)无法d 16 位的字符? Zq些原因, 在文件名, 文本文g, 环境变量{地? UCS-2 不适合作ؓ Unicode 的外部编? ?ISO 10646-1 Annex R ?RFC 2279 里定义的 UTF-8 ~码没有q些问题. 它是?Unix 风格的操作系l下使用 Unicode 的明昄Ҏ(gu). UTF-8 有一下特? 下列字节串用来表CZ个字W? 用到哪个串取决于该字W在 Unicode 中的序号. xxx 的位|由字符~码数的二进制表C的位填? 靠右的 x h少的特D意? 只用最短的那个_表达一个字W编码数的多字节? 注意在多字节串中, W一个字节的开?1"的数目就是整个串中字节的数目. 例如: Unicode 字符 U+00A9 = 1010 1001 (版权W号) ?UTF-8 里的~码? 11000010 10101001 = 0xC2 0xA9 而字W?U+2260 = 0010 0010 0110 0000 (不等? ~码? 11100010 10001001 10100000 = 0xE2 0x89 0xA0 q种~码的官方名字拼写ؓ UTF-8, 其中 UTF 代表 UCS Transformation Format. 请勿在Q何文档中用其他名?(比如 utf8 ?UTF_8) 来表C?UTF-8, 当然除非你指的是一个变量名而不是这U编码本w? 在大U?1993 q之后开发的大多数现代编E语a都有一个特别的数据cd, 叫做 Unicode/ISO 10646-1 字符. ?Ada95 中叫 Wide_Character, ?Java 中叫 char. ISO C 也详l说明了处理多字节编码和宽字W?(wide characters) 的机? 1994 q?9 ?Amendment 1 to ISO C 发表时又加入了更? q些机制主要是ؓ各类东亚~码而设计的, 它们比处?UCS 所需的要健壮得多. UTF-8 ?ISO C 标准调用多字节字W串的编码的一个例? wchar_t cd可以用来存放 Unicode 字符.谈谈Unicode~码Q简要解释UCS、UTF、BMP、BOM{名?/h2>
0、big endian和little endian
1、字W编码、内码,带介绍汉字~码
2、Unicode、UCS和UTF
2.1、内码和code page
3、UCS-2、UCS-4、BMP
4、UTF~码
UCS-2~码(16q制)
UTF-8 字节?二进?
0000 - 007F
0xxxxxxx
0080 - 07FF
110xxxxx 10xxxxxx
0800 - FFFF
1110xxxx 10xxxxxx 10xxxxxx
5、UTF的字节序和BOM
6、进一步的参考资?/h3>
附录1 再说说区位码、GB2312、内码和代码?/h3>
“GB2312的原文还是区位码Q从Z码到内码Q需要在高字节和低字节上分别加上A0?#8221;
如果原作者用的代码和ISO8859-1兼容Q就不会出现q了?/p>
文章二,本文转蝲?http://www.donews.net/holen/archive/2004/11/30/188182.aspx
unicode.org制定的编码机? 要将全世界常用文字都函括q去.
?.0中是16位编? 由U+0000到U+FFFF. 每个2byte码对应一个字W? ?.0开始抛弃了16位限? 原来?6位作为基本位q面, 另外增加?6个位q面, 相当?0位编? ~码范围0?x10FFFF.
UCS:
ISO制定的ISO10646标准所定义?Universal Character Set, 采用4byte~码.
Unicode与UCS的关p?
ISO与unicode.org是两个不同的l织, 因此最初制定了不同的标? 但自从unicode2.0开? unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646不会给出0x10FFFF的UCS-4~码赋? 使得两者保持一?
UCS的编码方?
UTF: Unicode/UCS Transformation Format
----------------------------------------------------------原文------------------------------------------------------------------------------------
* 与CPU字节序无关, 可以在不同^C间交?br>* 定w能力? M一个字节损坏后, 最多只会导致一个编码码位损? 不会N错误(如GB码错一个字节就会整行ؕ?
----------------------------------------------------------U正?-----------------------------------------------------------------------------------
* 与CPU字节序无关, 可以在不同^C间交?br>* 定w能力? M一个字节损坏后, 最多只会导致一个编码码位损? 不会N错误(如GB码错一个字节就会整行ؕ?
UTF与unicode的关p?
Unicode是一个字W集, 可以看作为内?
而UTF是一U编码方? 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接是unicode~码, 没有变换, 但它包含?x00在编码内, ?56字节码的W一个byte都是0x00, 在操作系l?C语言)中有Ҏ(gu)意义, 会引起问? 采用UTF-8~码对unicode的直接编码作些变换可以避免这问题, q带来一些优?
中国国标~码:
GB 18030是中国所有非手持/嵌入式计机pȝ的强制实施标?
-------------------------------
什么是 UCS ?ISO 10646?
什么是l合字符?
什么是 UCS 实现U别?
什么是 Unicode?
那么 Unicode ?ISO 10646 不同在什么地?
什么是 UTF-8?
U-00000000 - U-0000007F:
0xxxxxxx
U-00000080 - U-000007FF:
110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF:
1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF:
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF:
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF:
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
什么编E语a支持 Unicode?
何实现模p查扑֑Q?/p>
说到查找p考虑q样的问题,效率Q模p查找。说到效率hash表肯定是一U很好的解决Ҏ(gu)?br />但是如何实现模糊查找呢?一U最单的Ҏ(gu)是这栗利用hashmap提高效率
Ҏ(gu)一Q?br />构造一|Q每个节点包含一个mapQ每个map中放着的是很多个节?br />因ؓ别名是汉字,我们使用汉字的unicodeQ唯一)作ؓkeyQvalue是包含q个字的节点。比?br />中国?>A
中华人民共和?>B
构造这样一个树 ,rootMap(key=?value=node1)-->
|-(key=?value=node2)-->node2包含map2(key=?value=A)
node1包含map1-- |
|-(key=?value=node3)-->node3包含map3(key=?value=node4)-->node4
包含map4(keyQ民 value=node5)-->node5包含map5以此cLQ这样就建立了一个树型结?/p>
输入“中”,直接把属于中的一支拿出来
输入“中华”把属于中华的一支拿出来?br />但是事实证明q个Ҏ(gu)是个不好的办?因ؓ存在以下问题?br />1,当别名达?0000多个的时候占用内?00m也就是说Q空间消耗大
2,当第一个字不准的时候,模糊查询失效
虽然有改q方法,但是改进I间不大
Ҏ(gu)二:
Ҏ(gu)二来源于选D的思想Q所以用人来代替地名更合适,比如说有10个hQ每个h都有很多的名字,
姓名Q字Q^名,曄名等{?/p>
虽然别名是多的,但是真是地点是比较?yu)的Q徏立一?0长度的数l,把这些h~号Q?br />你输入一些字例如“舒庆春舍于”,来投,我把你输入的字一个一个去查找Q?br />先查扑ֈ名包含“舒”的所有hQ每人投一,
再查扑ֈ名包含“庆”的所有hQ每人投一,
再查扑ֈ名包含“春”的所有hQ每人投一,
依此cLQ最后我?0个h中找出票数最多的?/p>
q个的优点:
模糊查询更有效,占用内存更少Q减交互(用户可以多输入一些相关信息)Q一定能查到l果(相对?
注:Z么要减少交互呢,因ؓ有些情况下交互越越好(例如短信Q因为收费和录入ȝ的原因)
~点Q?br />1,因ؓ操作多,查询多,效率低下
2,当实际的“h”变的非常多的时候,出现I间不?/p>
但是q个Ҏ(gu)的可优化性很强,因ؓZ取名字是有规律的Q用到的字可能很多,常用字却很少Q?br />所以我们可以把一些常用字对应的h先查出来Q在查询的时候直接用这些结果。这L?p得到优化
对于~点2,我们可以实现q样的方法,默认不徏立Q何数l,建立一个空map,当这个h被第一ơ投的时候他q入mapQ这P那些被投0的人就不会q入Q大大减了I间费Q但是如果被投票的h很多呢可以模仿内存的实现方式Q实现部分存到硬盘,采取换入换出的方式,因ؓ每个人都得到q_数的机会很,大部分时候是某些人得到大多数的票Q所以换入换出应该不是很频繁Q问题二也得C一定程度的解决?/p>
之后想不到别的了,但是在模p记忆中q应Ҏ(gu)个别的,于是L覆去的想Q忽然好像有个脚Ƨ几里得
法的东西,但具体内容全部和饭一起吃了,哎!google一下,发现果然是这个。实现方?br /> ID
public static int getNumOne(int m,int n){
int num=Math.abs(m-n);
if (num > m){
num=m;
}
if(num >n){
num=n;
}
for(int i=num;i>0;i--){
if(m%i==0 && n%i==0){
num=i;
break;
}
}
return num;
}
Ƨ几里得
public static int getNumTwo(int m,int n){
int num=1;
if(m>n){
num=getNumTwo(m-n,n);
}else if(m<n){
num=getNumTwo(n-m,m);
}else if(m==n){
num=n;
}
return num;
}
改进法
public static int getNumThree(int m,int n){
int num=1;
while(num>0){
num=m%n;
m=n;
n=num;
}
return m;
}
字符是各U文字和W号的ȝQ包括各国家文字、标点符受图形符受数字等。字W集是多个字W的集合Q字W集U类较多Q每个字W集包含的字W个C同,常见字符集名UͼASCII字符集、GB2312字符集、BIG5字符集?GB 18030字符集、Unicode字符集等。计机要准的处理各种字符集文字,需要进行字W编码,以便计算够识别和存储各种文字?/p>
中文文字数目大,而且q分为简体中文和J体中文两种不同书写规则的文字,而计机最初是按英语单字节字符设计的,因此Q对中文字符q行~码Q是中文信息交流的技术基。本文将按照字符集的旉序讨论几种典型的字W集Q选取几种代表性的中文字符集,研究历史由来、特炏V技术特征?/p>
ASCII 字符?/strong>
1Q名U的由来
ASCIIQAmerican Standard Code for Information InterchangeQ美国信息互换标准代码)是基于罗马字母表的一套电(sh)脑编码系l?/p>
2Q特?/p>
它主要用于显C现代英语和其他西欧语言。它是现今最通用的单字节~码pȝQƈ{同于国际标准ISO 646?/p>
3Q包含内?/p>
控制字符Q回车键、退根{换行键{?/p>
可显C字W:英文大小写字W、阿拉伯数字和西文符?/p>
4Q技术特?/p>
7位(bitsQ表CZ个字W,?28字符
5QASCII扩展字符?/p>
7位编码的字符集只能支?28个字W,Z表示更多的欧z常用字W对ASCIIq行了扩展,ASCII扩展字符集?位(bitsQ表CZ个字W,?56字符?/p>
ASCII扩展字符集比ASCII字符集扩充出来的W号包括表格W号、计符受希腊字母和Ҏ(gu)的拉丁符受?
GB2312 字符?/strong>
1Q名U的由来
GB2312又称为GB2312-80字符集,全称为《信息交换用汉字~码字符集·基本集》,由原中国国家标准d发布Q?981q??日实施?/p>
2Q特?/p>
GB2312是中国国家标准的体中文字W集。它所收录的汉字已l覆?9.75%的用频率,基本满了汉字的计算机处理需要。在中国大陆和新加坡获广泛用?/p>
3Q包含内?/p>
GB2312收录化汉字及一般符受序受数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符受汉语注韛_母,?7445 个图形字W。其中包?763个汉字,其中一U汉?755个,二汉字3008个;包括拉丁字母、希腊字母、日文^假名及片假名字母、俄语西里尔字母在内?82个全角字W?
4Q技术特?/p>
Q?Q分C:
GB2312中对所收汉字进行了“分区”处理,每区含有94个汉?W号。这U表C方式也UCؓZ码?/p>
各区包含的字W如下:01-09ZؓҎ(gu)W号Q?6-55Zؓ一U汉字,按拼x序;56-87Zؓ二汉字Q按部首/W画排序Q?0-15区及88-94区则未有~码?/p>
Q?Q双字节表示
两个字节中前面的字节为第一字节Q后面的字节为第二字节。习惯上U第一字节为“高字节?Q而称W二字节为“低字节”?/p>
“高位字节”用了0xA1-0xF7(?1-87区的区号加上0xA0)Q“低位字节”用了0xA1-0xFE(?1-94加上0xA0)?/p>
5Q编码D?/p>
以GB2312字符集的W一个汉字“啊”字ZQ它的区?6Q位?1Q则Z码是1601Q在大多数计机E序中,高字节和低字节分别加0xA0得到E序的汉字处理编?xB0A1。计公式是Q?xB0=0xA0+16, 0xA1=0xA0+1?/p>
BIG5 字符?/strong>
1Q名U的由来
又称大五码或五大码,1984q由台湾财团法h信息工业{进会和五间软g公司宏碁 (Acer)、神?(MiTAC)、佳佟뀁零?(Zero One)、大?(FIC)创立Q故U大五码?/p>
Big5码的产生Q是因ؓ当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码{,彼此不能兼容Q另一斚wQ台湾政府当时尚未推出官方的汉字~码Q而中国大陆的GB2312~码亦未有收录繁体中文字?/p>
2Q特?/p>
Big5字符集共收录13,053个中文字Q该字符集在中国台湾使用。耐hd的是该字W集重复地收录了两个相同的字Q“兀?0xA461?xC94A)、“嗀?0xDCD1?xDDFC)?/p>
3Q字W编码方?/p>
Big5码用了双字节储存方法,以两个字节来~码一个字。第一个字节称为“高位字节”,W二个字节称为“低位字节”。高位字节的~码范围0xA1-0xF9Q低位字节的~码范围0x40-0x7E?xA1-0xFE?/p>
各编码范围对应的字符cd如下Q?xA140-0xA3BF为标点符受希腊字母及Ҏ(gu)W号Q另外于0xA259-0xA261Q存放了双音节度量衡单位用字Q兙兛兞兝兡兣嗧瓩糎Q?xA440-0xC67E为常用汉字,先按W划再按部首排序Q?xC940-0xF9D5为次常用汉字Q亦是先按笔划再按部首排序?/p>
4QBig5 的局限?/p>
管Big5码内包含一万多个字W,但是没有考虑C会上流通的人名、地名用字、方a用字、化学及生物U等用字Q没有包含日文^假名及片假名字母?/p>
例如台湾视“着”ؓ“著”的异体字,故没有收录“着”字。康熙字怸的一些部首用?如“亠”、“疒”、“R”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中?/p>
GB18030 字符?/strong>
1Q名U的由来
GB 18030的全U是GB18030-2000《信息交换用汉字~码字符集基本集的扩充》,是我国政府于2000q??7日发布的新的汉字~码国家标准Q?001q??1日后在中国市Z发布的Y件必ȝ合本标准
2Q特?/p>
GB 18030字符集标准的出台l过q泛参与和论证,来自国内外知名信息技术行业的公司Q信息业部和原国家质量技术监督局联合实施?/p>
GB 18030字符集标准解x字、日文假名、朝鲜语和中国少数民族文字组成的大字W集计算机编码问题。该标准的字Wȝ码空间超q?50万个~码位,收录?7484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满中国大陆、香港、台湾、日本和韩国{东亚地Z息交换多文种、大字量、多用途、统一~码格式的要求。ƈ且与Unicode 3.0版本兼容Q填补Unicode扩展字符字汇“统一汉字扩展A”的内容。ƈ且与以前的国家字W编码标准(GB2312QGB13000.1Q兼宏V?/p>
3Q编码方?/p>
GB 18030标准采用单字节、双字节和四字节三种方式对字W编码。单字节部分使用0×00?×7F?对应于ASCII码的相应?。双字节部分Q首字节码从0×81?×FEQ尾字节码位分别?×40?×7E?×80?×FE。四字节部分采用GB/T 11383未采用的0×30?×39作ؓ对双字节~码扩充的后~Q这h充的四字节编码,其范围ؓ0×81308130?×FE39FE39。其中第一、三个字节编码码位均?×81?×FEQ第二、四个字节编码码位均?×30?×39?/p>
4Q包含的内容
双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有x点符受表意文字描q符13个、增补的汉字和部?构g80个、双字节~码的欧元符L。 四字节部分收录了上述双字节字W之外的Q包括CJKl一汉字扩充A在内的GB 13000.1中的全部字符?/p>
Unicode字符?/strong>
1Q名U的由来
Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字W集的简Uͼ是由一个名?Unicode 学术学会(Unicode Consortium)的机构制订的字符~码pȝQ支持现今世界各U不同语a的书面文本的交换、处理及昄。该~码?990q开始研发,1994q正式公布,最新版本是2005q??1日的Unicode 4.1.0?/p>
2Q特?
Unicode是一U在计算Z使用的字W编码。它为每U语a中的每个字符讑֮了统一q且唯一的二q制~码Q以满跨语a、跨q_q行文本转换、处理的要求?/p>
3Q编码方?/p>
Unicode 标准始终使用十六q制数字Q而且在书写时在前面加上前~“U+”,例如字母“A”的~码?004116 和字W?”的~码?20AC16。所以“A”的~码书写为“U+0041”?/p>
4QUTF-8 ~码
UTF-8是Unicode的其中一个用方式?UTF?Unicode Translation FormatQ即把Unicode转做某种格式的意思?/p>
UTF-8便于不同的计机之间使用|络传输不同语言和编码的文字Q得双字节的Unicode能够在现存的处理单字节的pȝ上正传输?/p>
UTF-8使用可变长度字节来储?Unicode字符Q例如ASCII字母l箋使用1字节储存Q重x字、希腊字母或襉K字母等使用2字节来储存,而常用的汉字p使用3字节。辅助^面字W则使用4字节?/p>
5QUTF-16 ?UTF-32 ~码
UTF-32、UTF-16 ?UTF-8 ?Unicode 标准的编码字W集的字W编码方案,UTF-16 使用一个或两个未分配的 16 位代码单元的序列?Unicode 代码点进行编码;UTF-32 卛_每一?Unicode 代码点表CZؓ相同值的 32 位整?/p>
一Q休眠与唤醒
1,l典的生产者与消费者问?br />生者消费者现象的原型是这LQ?br />一个生产者生产,当缓冲区满了Q就自己休眠
一个消费者消费,当缓冲区IZQ就自己休眠
一个生产者生产,当生产一个品时Q就唤醒消费者(可以消费了)
一个消费者消费,当消费一个品时Q就唤醒生者(可以生?
无论是生产者,q是消费着Q当被唤醒的时候不一定马上执行,q需要获得cpu
◎这U设计生了一个问题,原因是需要一个count来记录品个敎ͼ而count的获得ƈ没有互斥
例如如下情况Q?br />消费者取得count=0Q但是还没来得及休眠自己的时候,发生了系l进E调度,切换到生产?br />生者生产了一个品后Q唤醒消费者,但是q个时候的消费者ƈ没有休眠Q所以唤醒丢?br />然后生者l生产,直到~冲满了Q自动休眠?br />但是q个时候的消费者也是休眠状态,没有人来唤醒他,所以两个都一直休眠下厅R?/p>
解决Ҏ(gu)Q?br />提供一个标志位Q当生者发送唤醒给消费者的时候,记录下来?Q当消费者要休眠之前查一下这个标志位Q如果是1׃休眠Q如果不是就休眠
q个Ҏ(gu)暂时解决了问题,考虑一下?br />如果是m个生产者,n个消费?m,n又很大的情况下,标志位就太多了?br />q种情况下情况下地解军_法见下一文?<互斥3-生者消费?gt;
q个Ҏ(gu)地实现程序如?
#define N=100
int count=0;
void product(void){
int item;
while(TRUE){
item=produce_item()
if(count==N)sleep();
insert_item(item);
count=count+1;
if (count==1)wakeup(consumer);
}
}
void consumer(void){
int item;
while(TRUE){
if(count==0)sleep();
item=remove_item();
count=count-1;
if(count==N-1)wakeup(product);
consume_item(item);
}
}
一Q考虑W一U自然情况:
解法Q所有哲学家拿v一只筷子,再拿旁边的一只,如果拿不到就{,{到可以拿了再拿
问题Q所有哲学家都拿起一只筷子,那就都吃不到饭,是死锁
二,解决上边的问?br />解法Q每个哲学家先拿左边的筷子,再拿双的筷子,如果拿不到右边的{子Q就攑ּ左边的筷子,{待一D|间再?br />问题Q试x有哲学家同时拿v{子Q同时放弃,再同时拿P同时攑ּ。。如此就q入了另外一U死循环
三,解决上边的问题:
解法Q在上边的情况下Q每ơ等待的旉变成随机一D|_q样基本能解决问题,例如以太|的工作方式是q样
问题Q再极少数情况下Q还是会出现冲突Q在一些要求较高的情况Q例如核늫的安全系l,q种情况试不允许出现?br />四,最l解x法:
解法Q用多个互斥信号量Q每个哲学家在想取筷子前先执行mutexQ然后判断一下左右的{子是否有h用,如果没有拿L子,否则׃拿筷?br />实现E序Q?br />#define N 5
#define Left (i+N-1)%N
#define Right (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int semaphore;
int state(N);
semapore mutex =1;
semaphore s(N);
void philosopher(int i){
while(TRUE){
think();
take_forks(i);
eat();
put_forks(i);
}
}
void tak_forks(int i){
down(&mutex);
state(i)=HUNGRY;
test(i);
up(&mutex);
down(&s[i]);
}
void put_forks(int i){
down(&mutex);
state(i)=THINK;
test(LEFT);
test(RIGHT);
up(&mutex);
}
void test(i){
if(state(i)==HUNGRY && state(LEFT)!=EATING && state(RIGHT)!=EATING){
state(i)=EATING;
up(&s[i])
}
}
q程都在{待下一个进E占有的资源?/p>
处理死锁的策略:
1,忽略该问题,你忽略它Q它也会忽略?br />2,试死锁q恢复,让死锁发生,,一旦检到Q恢?br />3,仔细对资源进行分配,动态避免死?br />4,通过破坏四个死锁条g之一
Ҏ(gu)一对应的时鸵鸟法Q就是出现这U死锁的可能性很低,比如操作pȝ的forkQ可?q出Cơ,
而在q段q程中,因ؓg{其它原因肯定要重新启动机器Q放弃fork损失太大Q就可以忽略q种死锁
Q象鸵鸟一P把头埋进沙子Q当什么都没发生?/p>
Ҏ(gu)二:ƈ恢复
恢复Ҏ(gu)?
抢占恢复
回退恢复
杀死进E恢?br />银行家算法:
如果?个h(A,B,C,D)去银行贷ƾ,银行有金?0个单位,
Ah最大ؓ6 ,A已经h1
Bh最大ؓ5 ,B已经h1
Ch最大ؓ4 ,C已经h2
Dh最大ؓ7 ,D已经h4
q个时候只有C的请求能通过Q因为现在还有可用贷?Q只有C才能完成Q然后释放更多,来让其它完成
q个时候如果给其它M一个单位的hQ那么所有的人都不能辑ֈ需求,完成?br />银行安题时个经典的问题Q但是很能得到实际的利用,因ؓ每个客户自己都不知道自己需要多资
源,同时Q也不知道有多少个客戗因Z停的有用户login ,logout
Ҏ(gu)四:破坏条g
1,破坏互斥条gQ不让独占出玎ͼ
例如不让一个用L占打印机Q如spooling技术,让多个用户同时进入spooling
问题Q可能在spooling中生死?br />2,破坏占有{待条g
这个进E需要的所有资源是不是可用Q如果可用分配,不可用的话就{待
问题Q进E要在开始知道自己需要多资源,q样可以使用银行家算法完成?br />但是资源利用不是最优?br />3,破坏不可抢占Q这个实现v来最困难
4,破坏闭环
把所有资源编P按照序h
饥饿Q?br />与死锁很接近的时饥饿
如果一个打印机的用,是通过某种法避免死锁Q但是每ơ都是最文件先打印Q这样就可能产生一
U情况,大的文g永远不能打印Q饥饿而死?/p>
相关的还有理发师问题Q?br />