﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-DANCE WITH JAVA-随笔分类-基础</title><link>http://www.blogjava.net/dreamstone/category/15446.html</link><description>开发出高质量的系统</description><language>zh-cn</language><lastBuildDate>Sun, 16 Sep 2007 10:06:55 GMT</lastBuildDate><pubDate>Sun, 16 Sep 2007 10:06:55 GMT</pubDate><ttl>60</ttl><item><title>配置tomcat5.5  jndi  各种配置方式 分析总结（mysql）</title><link>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 07 May 2007 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/115766.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/115766.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/115766.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: tomcat5.5 jndi 各种配置方式 分析总结&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/115766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-05-07 22:27 <a href="http://www.blogjava.net/dreamstone/archive/2007/05/07/115766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>看到两个写的很好的关于字符集,编码的文章，推荐大家看看，另外纠正了一下原文中的小bug(UTF-8 UniCode UTF-16 UCS 等)</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/28/83936.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 27 Nov 2006 17:11:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/28/83936.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/83936.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/28/83936.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/83936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/83936.html</trackback:ping><description><![CDATA[<h2>文章一，本文转载自:http://fmddlmyy.home4u.china.com/text6.html</h2>
<h2>谈谈Unicode编码，简要解释UCS、UTF、BMP、BOM等名词</h2>
<p>这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念，增进知识，类似于打RPG游戏的升级。整理这篇文章的动机是两个问题：</p>
<dl>
<dt>问题一：
<dd>
<p>使用Windows记事本的&#8220;另存为&#8221;，可以在GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件，Windows是怎样识别编码方式的呢？</p>
<p>我很早前就发现Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节，分别是FF、FE（Unicode）,FE、FF（Unicode big endian）,EF、BB、BF（UTF-8）。但这些标记是基于什么标准呢？</p>
<dt>问题二：
<dd>最近在网上看到一个ConvertUTF.c，实现了UTF-32、UTF-16和UTF-8这三种编码方式的相互转换。对于Unicode(UCS2)、GBK、UTF-8这些编码方式，我原来就了解。但这个程序让我有些糊涂，想不起来UTF-16和UCS2有什么关系。 </dd></dl>
<p>查了查相关资料，总算将这些问题弄清楚了，顺带也了解了一些Unicode的细节。写成一篇文章，送给有过类似疑问的朋友。本文在写作时尽量做到通俗易懂，但要求读者知道什么是字节，什么是十六进制。</p>
<h3>0、big endian和little endian</h3>
<p>big endian和little endian是CPU处理多字节数的不同方式。例如&#8220;汉&#8221;字的Unicode编码是6C49。那么写到文件里时，究竟是将6C写在前面，还是将49写在前面？如果将6C写在前面，就是big endian。如果将49写在前面，就是little endian。</p>
<p>&#8220;endian&#8221;这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开，由此曾发生过六次叛乱，一个皇帝送了命，另一个丢了王位。</p>
<p>我们一般将endian翻译成&#8220;字节序&#8221;，将big endian和little endian称作&#8220;大尾&#8221;和&#8220;小尾&#8221;。</p>
<h3>1、字符编码、内码，顺带介绍汉字编码</h3>
<p>字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码，为了处理汉字，程序员设计了用于简体中文的GB2312和用于繁体中文的big5。</p>
<p>GB2312(1980年)一共收录了7445个字符，包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7，低字节从A1-FE，占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。</p>
<p>GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号，它分为汉字区和图形符号区。汉字区包括21003个字符。</p>
<p>从ASCII、GB2312到GBK，这些编码方法是向下兼容的，即同一个字符在这些方案中总是有相同的编码，后面的标准支持更多的字符。在这些编码中，英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼，GB2312、GBK都属于双字节字符集 (DBCS)。</p>
<p>2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字，同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。从汉字字汇上说，GB18030在GB13000.1的20902个汉字的基础上增加了CJK扩展A的6582个汉字（Unicode码0x3400-0x4db5），一共收录了27484个汉字。</p>
<p>CJK就是中日韩的意思。Unicode为了节省码位，将中日韩三国语言中的文字统一编码。GB13000.1就是ISO/IEC 10646-1的中文版，相当于Unicode 1.1。</p>
<p>GB18030的编码采用单字节、双字节和4字节方案。其中单字节、双字节和GBK是完全兼容的。4字节编码的码位就是收录了CJK扩展A的6582个汉字。 例如：UCS的0x3400在GB18030中的编码应该是8139EF30，UCS的0x3401在GB18030中的编码应该是8139EF31。</p>
<p>微软提供了GB18030的升级包，但这个升级包只是提供了一套支持CJK扩展A的6582个汉字的新字体：新宋体-18030，并不改变内码。Windows 的内码仍然是GBK。</p>
<p>这里还有一些细节：</p>
<ul>
    <li>
    <p>GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。</p>
    <li>
    <p>对于任何字符编码，编码单元的顺序是由编码方案指定的，与endian无关。例如GBK的编码单元是字节，用两个字节表示一个汉字。 这两个字节的顺序是固定的，不受CPU字节序的影响。UTF-16的编码单元是word（双字节），word之间的顺序是编码方案指定的，word内部的字节排列才会受到endian的影响。后面还会介绍UTF-16。</p>
    <li>
    <p>GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析：在读取DBCS字符流时，只要遇到高位为1的字节，就可以将下两个字节作为一个双字节编码，而不用管低字节的高位是什么。</p>
    </li>
</ul>
<h3>2、Unicode、UCS和UTF</h3>
<p>前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容（更准确地说，是与ISO-8859-1兼容），与GB码不兼容。例如&#8220;汉&#8221;字的Unicode编码是6C49，而GB码是BABA。</p>
<p>Unicode也是一种字符编码方法，不过它是由国际组织设计，可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"，简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。</p>
<p>根据维基百科全书(http://zh.wikipedia.org/wiki/)的记载：历史上存在两个试图独立设计Unicode的组织，即国际标准化组织（ISO）和一个软件制造商的协会（unicode.org）。ISO开发了ISO 10646项目，Unicode协会开发了Unicode项目。</p>
<p>在1991年前后，双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果，并为创立一个单一编码表而协同工作。从Unicode2.0开始，Unicode项目采用了与ISO 10646-1相同的字库和字码。</p>
<p>目前两个项目仍都存在，并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是ISO 10646-3:2003。</p>
<p>UCS只是规定如何编码，并没有规定如何传输、保存这个编码。例如&#8220;汉&#8221;字的UCS编码是6C49，我可以用4个ascii数字来传输、保存这个编码；也可以用utf-8编码:3个连续的字节E6 B1 89来表示它。关键在于通信双方都要认可。UTF-8、UTF-7、UTF-16都是被广泛接受的方案。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。UTF是&#8220;UCS Transformation Format&#8221;的缩写。</p>
<p>IETF的RFC2781和RFC3629以RFC的一贯风格，清晰、明快又不失严谨地描述了UTF-16和UTF-8的编码方法。我总是记不得IETF是Internet Engineering Task Force的缩写。但IETF负责维护的RFC是Internet上一切规范的基础。</p>
<h4>2.1、内码和code page</h4>
<p>目前Windows的内核已经支持Unicode字符集，这样在内核上可以支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码，例如GBK，Windows不可能不支持现有的编码，而全部改用Unicode。</p>
<p>Windows使用代码页(code page)来适应各个国家和地区。code page可以被理解为前面提到的内码。GBK对应的code page是CP936。</p>
<p>微软也为GB18030定义了code page：CP54936。但是由于GB18030有一部分4字节编码，而Windows的代码页只支持单字节和双字节编码，所以这个code page是无法真正使用的。</p>
<h3>3、UCS-2、UCS-4、BMP</h3>
<p>UCS有两种格式：UCS-2和UCS-4。顾名思义，UCS-2就是用两个字节编码，UCS-4就是用4个字节（实际上只用了31位，最高位必须为0）编码。下面让我们做一些简单的数学游戏：</p>
<p>UCS-2有2^16=65536个码位，UCS-4有2^31=2147483648个码位。</p>
<p>UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows)，每行包含256个cells。当然同一行的cells只是最后一个字节不同，其余都相同。</p>
<p>group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中，高两个字节为0的码位被称作BMP。</p>
<p>将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节，就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外。</p>
<h3>4、UTF编码</h3>
<p>&#160;</p>
<p>UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下：</p>
<table width="75%" border=1>
    <tbody>
        <tr>
            <td>UCS-2编码(16进制)</td>
            <td>UTF-8 字节流(二进制)</td>
        </tr>
        <tr>
            <td>0000 - 007F</td>
            <td>0xxxxxxx</td>
        </tr>
        <tr>
            <td>0080 - 07FF</td>
            <td>110xxxxx 10xxxxxx</td>
        </tr>
        <tr>
            <td>0800 - FFFF</td>
            <td>1110xxxx 10xxxxxx 10xxxxxx</td>
        </tr>
    </tbody>
</table>
<p>例如&#8220;汉&#8221;字的Unicode编码是6C49。6C49在0800-FFFF之间，所以肯定要用3字节模板了：<font color=#0000ff>1110</font>xxxx <font color=#0000ff>10</font>xxxxxx <font color=#0000ff>10</font>xxxxxx。将6C49写成二进制是：0110 110001 001001， 用这个比特流依次代替模板中的x，得到：<font color=#0000ff>1110</font>0110 <font color=#0000ff>10</font>110001 <font color=#0000ff>10</font>001001，即E6 B1 89。</p>
<p>读者可以用记事本测试一下我们的编码是否正确。需要注意，UltraEdit在打开utf-8编码的文本文件时会自动转换为UTF-16，可能产生混淆。你可以在设置中关掉这个选项。更好的工具是Hex Workshop。</p>
<p>UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码，UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码，定义了一个算法。不过由于实际使用的UCS2，或者UCS4的BMP必然小于0x10000，所以就目前而言，可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案，UTF-16却要用于实际的传输，所以就不得不考虑字节序的问题。</p>
<h3>5、UTF的字节序和BOM</h3>
<p>UTF-8以字节为编码单元，没有字节序的问题。UTF-16以两个字节为编码单元，在解释一个UTF-16文本前，首先要弄清楚每个编码单元的字节序。例如&#8220;奎&#8221;的Unicode编码是594E，&#8220;乙&#8221;的Unicode编码是4E59。如果我们收到UTF-16字节流&#8220;594E&#8221;，那么这是&#8220;奎&#8221;还是&#8220;乙&#8221;？</p>
<p>Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是&#8220;Bill Of Material&#8221;的BOM表，而是Byte Order Mark。BOM是一个有点小聪明的想法：</p>
<p>在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符，它的编码是FEFF。而FFFE在UCS中是不存在的字符，所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前，先传输字符"ZERO WIDTH NO-BREAK SPACE"。</p>
<p>这样如果接收者收到FEFF，就表明这个字节流是Big-Endian的；如果收到FFFE，就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。</p>
<p>UTF-8不需要BOM来表明字节顺序，但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF（读者可以用我们前面介绍的编码方法验证一下）。所以如果接收者收到以EF BB BF开头的字节流，就知道这是UTF-8编码了。</p>
<p>Windows就是使用BOM来标记文本文件的编码方式的。</p>
<h3>6、进一步的参考资料</h3>
<p>本文主要参考的资料是 "Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)。</p>
<p>我还找了两篇看上去不错的资料，不过因为我开始的疑问都找到了答案，所以就没有看：</p>
<ol>
    <li>"Understanding Unicode A general introduction to the Unicode Standard" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter04a)
    <li>"Character set encoding basics Understanding character set encodings and legacy encodings" (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;item_id=IWS-Chapter03) </li>
</ol>
<p>我写过UTF-8、UCS-2、GBK相互转换的软件包，包括使用Windows API和不使用Windows API的版本。以后有时间的话，我会整理一下放到我的个人主页上(http://fmddlmyy.home4u.china.com)。</p>
<p>我是想清楚所有问题后才开始写这篇文章的，原以为一会儿就能写好。没想到考虑措辞和查证细节花费了很长时间，竟然从下午1:30写到9:00。希望有读者能从中受益。</p>
<h3>附录1 再说说区位码、GB2312、内码和代码页</h3>
<p>有的朋友对文章中这句话还有疑问：<br>&#8220;GB2312的原文还是区位码，从区位码到内码，需要在高字节和低字节上分别加上A0。&#8221;</p>
<p>我再详细解释一下：</p>
<p>&#8220;GB2312的原文&#8221;是指国家1980年的一个标准《中华人民共和国国家标准 信息交换用汉字编码字符集 基本集 GB 2312-80》。这个标准用两个数来编码汉字和中文符号。第一个数称为&#8220;区&#8221;，第二个数称为&#8220;位&#8221;。所以也称为区位码。1-9区是中文符号，16-55区是一级汉字，56-87区是二级汉字。现在Windows也还有区位输入法，例如输入1601得到&#8220;啊&#8221;。（这个区位输入法可以自动识别16进制的GB2312和10进制的区位码，也就是说输入B0A1同样会得到&#8220;啊&#8221;。）</p>
<p>内码是指操作系统内部的字符编码。早期操作系统的内码是与语言相关的。现在的Windows在系统内部支持Unicode，然后用代码页适应各种语言，&#8220;内码&#8221;的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码。</p>
<p>内码这个词汇，并没有什么官方的定义，代码页也只是微软这个公司的叫法。作为程序员，我们只要知道它们是什么东西，没有必要过多地考证这些名词。</p>
<p>Windows中有缺省代码页的概念，即缺省用什么编码来解释字符。例如Windows的记事本打开了一个文本文件，里面的内容是字节流：BA、BA、D7、D6。Windows应该去怎么解释它呢？</p>
<p>是按照Unicode编码解释、还是按照GBK解释、还是按照BIG5解释，还是按照ISO8859-1去解释？如果按GBK去解释，就会得到&#8220;汉字&#8221;两个字。按照其它编码解释，可能找不到对应的字符，也可能找到错误的字符。所谓&#8220;错误&#8221;是指与文本作者的本意不符，这时就产生了乱码。</p>
<p>答案是Windows按照当前的缺省代码页去解释文本文件里的字节流。缺省代码页可以通过控制面板的区域选项设置。记事本的另存为中有一项ANSI，其实就是按照缺省代码页的编码方法保存。</p>
<p>Windows的内码是Unicode，它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码，用户又安装了对应的代码页，Windows就能正确显示，例如在HTML文件中就可以指定charset。</p>
<p>有的HTML文件作者，特别是英文作者，认为世界上所有人都使用英文，在文件中不指定charset。如果他使用了0x80-0xff之间的字符，中文Windows又按照缺省的GBK去解释，就会出现乱码。这时只要在这个html文件中加上指定charset的语句，例如：<br>&lt;meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"&gt;<br>如果原作者使用的代码页和ISO8859-1兼容，就不会出现乱码了。</p>
<p>再说区位码，啊的区位码是1601，写成16进制是0x10,0x01。这和计算机广泛使用的ASCII编码冲突。为了兼容00-7f的ASCII编码，我们在区位码的高、低字节上分别加上A0。这样&#8220;啊&#8221;的编码就成为B0A1。我们将加过两个A0的编码也称为GB2312编码，虽然GB2312的原文根本没提到这一点。 <br><br><strong>文章二，本文转载自:http://www.donews.net/holen/archive/2004/11/30/188182.aspx<br></strong></p>
<p>Unicode: <br><br>unicode.org制定的编码机制, 要将全世界常用文字都函括进去.<br>在1.0中是16位编码, 由U+0000到U+FFFF. 每个2byte码对应一个字符; 在2.0开始抛弃了16位限制, 原来的16位作为基本位平面, 另外增加了16个位平面, 相当于20位编码, 编码范围0到0x10FFFF.<br><br>UCS: <br><br>ISO制定的ISO10646标准所定义的 Universal Character Set, 采用4byte编码.<br><br>Unicode与UCS的关系:<br><br>ISO与unicode.org是两个不同的组织, 因此最初制定了不同的标准; 但自从unicode2.0开始, unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值, 使得两者保持一致.<br><br>UCS的编码方式:<br><br></p>
<li>UCS-2, 与unicode的2byte编码基本一样. <br>
<li>UCS-4, 4byte编码, 目前是在UCS-2前加上2个全零的byte.<br><br>UTF: Unicode/UCS Transformation Format<br>----------------------------------------------------------原文------------------------------------------------------------------------------------
<li>UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:<br>* 与CPU字节顺序无关, 可以在不同平台之间交流<br>* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) <br>
<li>UTF-16, 16bit编码, 是变长码, 大致相当于20位编码, 值在0到0x10FFFF之间, 基本上就是unicode编码的实现. 它是变长码, 与CPU字序有关, 但因为最省空间, 常作为网络传输的外码.
<p>----------------------------------------------------------原文------------------------------------------------------------------------------------<br>----------------------------------------------------------纠正后------------------------------------------------------------------------------------ </p>
<li>UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:<br>* 与CPU字节顺序无关, 可以在不同平台之间交流<br>* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) <br>
<li>UTF-16, 16bit编码, 是定长码,&nbsp; 基本上就是unicode编码的实现. 与CPU字序有关
<p>----------------------------------------------------------纠正后-----------------------------------------------------------------------------------</p>
<li>UTF-16是unicode的preferred encoding. <br>
<li>UTF-32, 仅使用了unicode范围(0到0x10FFFF)的32位编码, 相当于UCS-4的子集.<br><br>UTF与unicode的关系:<br><br>Unicode是一个字符集, 可以看作为内码.<br>而UTF是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题, 并带来一些优点.<br><br>中国国标编码:<br>
<li>GB 13000: 完全等同于ISO 10646-1/Unicode 2.1, 今后也将随ISO 10646/Unicode的标准更改而同步更改.<br>
<li>GBK: 对GB2312的扩充, 以容纳GB2312字符集范围以外的Unicode 2.1的统一汉字部分, 并且增加了部分unicode中没有的字符. <br>
<li>GB 18030-2000: 基于GB 13000, 作为Unicode 3.0的GBK扩展版本, 覆盖了所有unicode编码, 地位等同于UTF-8, UTF-16, 是一种unicode编码形式. 变长编码, 用单字节/双字节/4字节对字符编码. GB18030向下兼容GB2312/GBK. <br>GB 18030是中国所有非手持/嵌入式计算机系统的强制实施标准.
<p><br>-------------------------------<br></p>
<p><br>&nbsp;</p>
<h2>什么是 UCS 和 ISO 10646?</h2>
<p>国际标准 ISO 10646 定义了 通用字符集 (Universal Character Set, UCS). UCS 是所有其他字符集标准的一个超集. 它保证与其他字符集是双向兼容的. 就是说, 如果你将任何文本字符串翻译到 UCS格式, 然后再翻译回原编码, 你不会丢失任何信息.</p>
<p>UCS 包含了用于表达所有已知语言的字符. 不仅包括拉丁语,希腊语, 斯拉夫语,希伯来语,阿拉伯语,亚美尼亚语和乔治亚语的描述, 还包括中文, 日文和韩文这样的象形文字, 以及 平假名, 片假名, 孟加拉语, 旁遮普语果鲁穆奇字符(Gurmukhi), 泰米尔语, 印.埃纳德语(Kannada), Malayalam, 泰国语, 老挝语, 汉语拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他数也数不清的语. 对于还没有加入的语言, 由于正在研究怎样在计算机中最好地编码它们, 因而最终它们都将被加入. 这些语言包括 Tibetian, 高棉语, Runic(古代北欧文字), 埃塞俄比亚语, 其他象形文字, 以及各种各样的印-欧语系的语言, 还包括挑选出来的艺术语言比如 Tengwar, Cirth 和 克林贡语(Klingon). UCS 还包括大量的图形的, 印刷用的, 数学用的和科学用的符号, 包括所有由 TeX, Postscript, MS-DOS，MS-Windows, Macintosh, OCR 字体, 以及许多其他字处理和出版系统提供的字符.</p>
<p>ISO 10646 定义了一个 31 位的字符集. 然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD). 这个 UCS 的 16位子集称为 基本多语言面 (Basic Multilingual Plane, BMP). 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了. ISO 10646-1 标准第一次发表于 1993 年, 定义了字符集与 BMP 中内容的架构. 定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中, 但也许要过好几年才能完成. 新的字符仍源源不断地加入到 BMP 中, 但已经存在的字符是稳定的且不会再改变了.</p>
<p>UCS 不仅给每个字符分配一个代码, 而且赋予了一个正式的名字. 表示一个 UCS 或 Unicode 值的十六进制数, 通常在前面加上 "U+", 就象 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 以外的大范围的编码是为私用保留的.</p>
<h2>什么是组合字符?</h2>
<p>UCS里有些编码点分配给了 组合字符.它们类似于打字机上的无间隔重音键. 单个的组合字符不是一个完整的字符. 它是一个类似于重音符或其他指示标记, 加在前一个字符后面. 因而, 重音符可以加在任何字符后面. 那些最重要的被加重的字符, 就象普通语言的正字法(orthographies of common languages)里用到的那种, 在 UCS 里都有自己的位置, 以确保同老的字符集的向后兼容性. 既有自己的编码位置, 又可以表示为一个普通字符跟随一个组合字符的被加重字符, 被称为 预作字符(precomposed characters). UCS 里的预作字符是为了同没有预作字符的旧编码, 比如 ISO 8859, 保持向后兼容性而设的. 组合字符机制允许在任何字符后加上重音符或其他指示标记, 这在科学符号中特别有用, 比如数学方程式和国际音标字母, 可能会需要在一个基本字符后组合上一个或多个指示标记.</p>
<p>组合字符跟随着被修饰的字符. 比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"), 既可以表示为 UCS 码 U+00C4 的预作字符, 也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合. 当需要堆叠多个重音符, 或在一个基本字符的上面和下面都要加上组合标记时, 可以使用多个组合字符. 比如在泰国文中, 一个基本字符最多可加上两个组合字符.</p>
<h2>什么是 UCS 实现级别?</h2>
<p>不是所有的系统都需要支持象组合字符这样的 UCS 里所有的先进机制. 因此 ISO 10646 指定了下列三种实现级别: </p>
<dl>
<dt>级别1
<dd>不支持组合字符和 Hangul Jamo 字符 (一种特别的, 更加复杂的韩国文的编码, 使用两个或三个子字符来编码一个韩文音节)
<dt>级别2
<dd>类似于级别1, 但在某些文字中, 允许一列固定的组合字符 (例如, 希伯来文, 阿拉伯文, Devangari, 孟加拉语, 果鲁穆奇语, Gujarati, Oriya, 泰米尔语, Telugo, 印.埃纳德语, Malayalam, 泰国语和老挝语). 如果没有这最起码的几个组合字符, UCS 就不能完整地表达这些语言.
<dt>级别3
<dd>支持所有的 UCS 字符, 例如数学家可以在任意一个字符上加上一个 tilde(颚化符号,西班牙语字母上面的～)或一个箭头(或两者都加). </dd></dl>
<h2>什么是 Unicode?</h2>
<p>历史上, 有两个独立的, 创立单一字符集的尝试. 一个是<a href="http://www.iso.ch/">国际标准化组织(ISO)</a>的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 <a href="http://www.unicode.org/">Unicode 项目</a>. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展.</p>
<h2>那么 Unicode 和 ISO 10646 不同在什么地方?</h2>
<p>Unicode 协会公布的 <a href="http://www.unicode.org/unicode/standard/standard.html">Unicode 标准</a> 严密地包含了 ISO 10646-1 实现级别3的基本多语言面. 在两个标准里所有的字符都在相同的位置并且有相同的名字.</p>
<p>Unicode 标准额外定义了许多与字符有关的语义符号学, 一般而言是对于实现高质量的印刷出版系统的更好的参考. Unicode 详细说明了绘制某些语言(比如阿拉伯语)表达形式的算法, 处理双向文字(比如拉丁与希伯来文混合文字)的算法和 排序与字符串比较 所需的算法, 以及其他许多东西.</p>
<p>另一方面, ISO 10646 标准, 就象广为人知的 ISO 8859 标准一样, 只不过是一个简单的字符集表. 它指定了一些与标准有关的术语, 定义了一些编码的别名, 并包括了规范说明, 指定了怎样使用 UCS 连接其他 ISO 标准的实现, 比如 ISO 6429 和 ISO 2022. 还有一些与 ISO 紧密相关的, 比如 ISO 14651 是关于 UCS 字符串排序的.</p>
<p>考虑到 Unicode 标准有一个易记的名字, 且在任何好的书店里的 Addison-Wesley 里有, 只花费 ISO 版本的一小部分, 且包括更多的辅助信息, 因而它成为使用广泛得多的参考也就不足为奇了. 然而, 一般认为, 用于打印 ISO 10646-1 标准的字体在某些方面的质量要高于用于打印 Unicode 2.0的. 专业字体设计者总是被建议说要两个标准都实现, 但一些提供的样例字形有显著的区别. ISO 10646-1 标准同样使用四种不同的风格变体来显示表意文字如中文, 日文和韩文 (CJK), 而 Unicode 2.0 的表里只有中文的变体. 这导致了普遍的认为 Unicode 对日本用户来说是不可接收的传说, 尽管是错误的.</p>
<h2>什么是 UTF-8?</h2>
<p>首先 UCS 和 Unicode 只是分配整数给字符的编码表. 现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将 Unicode 文本存储为 2 个 或 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 和 UCS-4. 除非另外指定, 否则大多数的字节都是这样的(Bigendian convention). 将一个 ASCII 或 Latin-1 的文件转换成 UCS-2 只需简单地在每个 ASCII 字节前插入 0x00. 如果要转换成 UCS-4, 则必须在每个 ASCII 字节前插入三个 0x00.</p>
<p>在 Unix 下使用 UCS-2 (或 UCS-4) 会导致非常严重的问题. 用这些编码的字符串会包含一些特殊的字符, 比如 '\0' 或 '/', 它们在 文件名和其他 C 库函数参数里都有特别的含义. 另外, 大多数使用 ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方, UCS-2 不适合作为 Unicode 的外部编码.</p>
<p>在 ISO 10646-1 <a href="http://www.cl.cam.ac.uk/~mgk25/ucs/ISO-10646-UTF-8.html">Annex R</a> 和 <a href="ftp://ftp.funet.fi/mirrors/nic.nordu.net/rfc/rfc2279.txt">RFC 2279</a> 里定义的 UTF-8 编码没有这些问题. 它是在 Unix 风格的操作系统下使用 Unicode 的明显的方法.</p>
<p>UTF-8 有一下特性: </p>
<ul>
    <li>UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的.
    <li>所有 &gt;U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分.
    <li>表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响.
    <li>可以编入所有可能的 2<sup>31</sup>个 UCS 代码
    <li>UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长.
    <li>Bigendian UCS-4 字节串的排列顺序是预定的.
    <li>字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到. </li>
</ul>
<p>下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.</p>
<div align=center>
<center>
<table border=1>
    <tbody>
        <tr>
            <td>U-00000000 - U-0000007F: </td>
            <td>0<em>xxxxxxx</em></td>
        </tr>
        <tr>
            <td>U-00000080 - U-000007FF: </td>
            <td>110<em>xxxxx</em> 10<em>xxxxxx</em></td>
        </tr>
        <tr>
            <td>U-00000800 - U-0000FFFF: </td>
            <td>1110<em>xxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em></td>
        </tr>
        <tr>
            <td>U-00010000 - U-001FFFFF: </td>
            <td>11110<em>xxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em></td>
        </tr>
        <tr>
            <td>U-00200000 - U-03FFFFFF: </td>
            <td>111110<em>xx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em></td>
        </tr>
        <tr>
            <td>U-04000000 - U-7FFFFFFF: </td>
            <td>1111110<em>x</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em></td>
        </tr>
    </tbody>
</table>
</center></div>
<p>xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.</p>
<p><strong>例如</strong>: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为:</p>
<blockquote>
<p>11000010 10101001 = 0xC2 0xA9</p>
</blockquote>
<p>而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:</p>
<blockquote>
<p>11100010 10001001 10100000 = 0xE2 0x89 0xA0</p>
</blockquote>
<p>这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 <strong>U</strong>CS <strong>T</strong>ransformation <strong>F</strong>ormat. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.</p>
<h2>什么编程语言支持 Unicode?</h2>
<p>在大约 1993 年之后开发的大多数现代编程语言都有一个特别的数据类型, 叫做 Unicode/ISO 10646-1 字符. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char.</p>
<p>ISO C 也详细说明了处理多字节编码和宽字符 (wide characters) 的机制, 1994 年 9 月 <a href="http://www.lysator.liu.se/c/na1.html">Amendment 1 to ISO C</a> 发表时又加入了更多. 这些机制主要是为各类东亚编码而设计的, 它们比处理 UCS 所需的要健壮得多. UTF-8 是 ISO C 标准调用多字节字符串的编码的一个例子, <em>wchar_t</em> 类型可以用来存放 Unicode 字符.</p>
</li>
<img src ="http://www.blogjava.net/dreamstone/aggbug/83936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-28 01:11 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/28/83936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模糊查询的思考</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/22/71224.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Thu, 21 Sep 2006 17:15:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/22/71224.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71224.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/22/71224.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71224.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71224.html</trackback:ping><description><![CDATA[
		<p>现实中经常有这样的问题，我们要从很多东西里边找到一个东西，而这些东西有很多别名，例如地点。如</p>
		<p>何实现模糊查找呢？</p>
		<p>说到查找就要考虑这样的问题，效率，模糊查找。说到效率hash表肯定是一种很好的解决方案。<br />但是如何实现模糊查找呢？一种最简单的方法是这样。利用hashmap提高效率<br />方法一：<br />构造一棵树，每个节点包含一个map，每个map中放着的是很多个节点<br />因为别名是汉字，我们使用汉字的unicode（唯一)作为key，value就是包含这个字的节点。比如<br />中国人-&gt;A<br />中华人民共和国-&gt;B<br />构造这样一个树 ,rootMap(key=中 value=node1)--&gt;</p>
		<p>                              |-(key=国 value=node2)--&gt;node2包含map2(key=人 value=A) <br />node1包含map1-- |<br />                              |-(key=华 value=node3)--&gt;node3包含map3(key=人 value=node4)--&gt;node4</p>
		<p>
				<br />包含map4(key＝民 value=node5)--&gt;node5包含map5以此类推，这样就建立了一个树型结构</p>
		<p>输入“中”，直接把属于中的一支拿出来<br />输入“中华”把属于中华的一支拿出来。<br />但是事实证明这个方案是个不好的办法,因为存在以下问题。<br />1,当别名达到50000多个的时候占用内存100m也就是说，空间消耗大<br />2,当第一个字不准确的时候，模糊查询失效<br />虽然有改进方法，但是改进空间不大</p>
		<p>方法二：<br />方法二来源于选举的思想，所以用人来代替地名更合适，比如说有10个人，每个人都有很多的名字，<br />姓名，字，乳名，曾用名等等</p>
		<p>虽然别名是多的，但是真是地点确是比较少的，建立一个10长度的数组，把这些人编号，<br />你输入一些字例如“舒庆春舍于”，来投票，我把你输入的字一个一个去查找，<br />先查找别名包含“舒”的所有人，每人投一票，<br />再查找别名包含“庆”的所有人，每人投一票，<br />再查找别名包含“春”的所有人，每人投一票，<br />依此类推，最后我在10个人中找出票数最多的人</p>
		<p>这个的优点：<br />模糊查询更有效，占用内存更少，减少交互（用户可以多输入一些相关信息），一定能查到结果(相对是)<br />注：为什么要减少交互呢，因为有些情况下交互越少越好（例如短信，因为收费和录入麻烦的原因）<br />缺点：<br />1,因为操作多，查询多，效率低下<br />2,当实际的“人”变的非常多的时候，出现空间不足。</p>
		<p>但是这个方法的可优化性很强，因为人们取名字是有规律的，用到的字可能很多，常用字却很少，<br />所以我们可以把一些常用字对应的人先查出来，在查询的时候直接使用这些结果。这样缺点1就能得到优化<br />对于缺点2,我们可以实现这样的方法，默认不建立任何数组，建立一个空map,当这个人被第一次投票的时候他进入map，这样，那些被投0票的人就不会进入，大大减少了空间浪费，但是如果被投票的人很多呢可以模仿内存的实现方式，实现部分存到硬盘，采取换入换出的方式，因为每个人都得到平均票数的机会很少，大部分时候是某些人得到大多数的票，所以换入换出应该不是很频繁，问题二也得到了一定程度的解决。</p>
		<p> </p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71224.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-22 01:15 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/22/71224.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最大公约数</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/22/71221.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Thu, 21 Sep 2006 16:12:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/22/71221.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/71221.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/22/71221.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/71221.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/71221.html</trackback:ping><description><![CDATA[
		<p>今天一次无意的思考中想起了最大公约数，想一下最大公约数的算法，第一反映是穷举，然后是短除，再</p>
		<p>之后就想不到别的了，但是在模糊记忆中还应改有个别的，于是翻来覆去的想，忽然好像有个脚欧几里得</p>
		<p>算法的东西，但具体内容全部和饭一起吃了，哎！google一下，发现果然是这个。实现方式<br /> 穷举<br /> public static int getNumOne(int m,int n){<br />  int num=Math.abs(m-n);<br />  if (num &gt; m){<br />   num=m;<br />  }<br />  if(num &gt;n){<br />   num=n;<br />  }<br />  for(int i=num;i&gt;0;i--){<br />   if(m%i==0 &amp;&amp; n%i==0){<br />    num=i;<br />    break;<br />   }<br />  }<br />  return num;<br /> }<br /> 欧几里得<br /> public static int getNumTwo(int m,int n){<br />  int num=1;<br />  if(m&gt;n){<br />   num=getNumTwo(m-n,n);<br />  }else if(m&lt;n){<br />   num=getNumTwo(n-m,m);<br />  }else if(m==n){<br />   num=n;<br />  }<br />  return num;<br /> }<br /> 改进算法<br /> public static int getNumThree(int m,int n){<br />  int num=1;<br />  while(num&gt;0){<br />   num=m%n;<br />   m=n;<br />   n=num;<br />  }<br />  return m;<br /> }<br /></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/71221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-22 00:12 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/22/71221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中文字符集与字符编码的基础知识 （转载）</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/20/70925.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 20 Sep 2006 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/20/70925.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/70925.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/20/70925.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/70925.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/70925.html</trackback:ping><description><![CDATA[
		<table class="fixedTable blogpost" cellspacing="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="ellipse">
										<span class="bvTitle" id="subjcns!56C9E8F1FFC74F4!154">
												<strong>中文字符集与字符编码的基础知识 </strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="bvh8">
										<strong>
										</strong>
								</td>
						</tr>
						<tr>
								<td id="msgcns!56C9E8F1FFC74F4!154">
										<div>
												<p>字符是各种文字和符号的总称，包括各国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合，字符集种类较多，每个字符集包含的字符个数不同，常见字符集名称：ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字，需要进行字符编码，以便计算机能够识别和存储各种文字。</p>
												<p>中文文字数目大，而且还分为简体中文和繁体中文两种不同书写规则的文字，而计算机最初是按英语单字节字符设计的，因此，对中文字符进行编码，是中文信息交流的技术基础。本文将按照字符集的时间顺序讨论几种典型的字符集，选取几种代表性的中文字符集，研究历史由来、特点、技术特征。</p>
												<p>
														<strong>ASCII 字符集</strong>
												</p>
												<p>1．名称的由来</p>
												<p>ASCII（American Standard Code for Information Interchange，美国信息互换标准代码）是基于罗马字母表的一套电脑编码系统。</p>
												<p>2．特点</p>
												<p>它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统，并等同于国际标准ISO 646。</p>
												<p>3．包含内容</p>
												<p>控制字符：回车键、退格、换行键等。</p>
												<p>可显示字符：英文大小写字符、阿拉伯数字和西文符号</p>
												<p>4．技术特征</p>
												<p>7位（bits）表示一个字符，共128字符</p>
												<p>5．ASCII扩展字符集</p>
												<p>7位编码的字符集只能支持128个字符，为了表示更多的欧洲常用字符对ASCII进行了扩展，ASCII扩展字符集使用8位（bits）表示一个字符，共256字符。</p>
												<p>ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。 </p>
												<p>
														<strong>GB2312 字符集</strong>
												</p>
												<p> 1．名称的由来</p>
												<p>GB2312又称为GB2312-80字符集，全称为《信息交换用汉字编码字符集·基本集》，由原中国国家标准总局发布，1981年5月1日实施。</p>
												<p>2．特点</p>
												<p>GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率，基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。</p>
												<p>3．包含内容</p>
												<p>GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母，共 7445 个图形字符。其中包括6763个汉字，其中一级汉字3755个，二级汉字3008个；包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。 </p>
												<p>4．技术特征</p>
												<p>（1）分区表示：</p>
												<p>GB2312中对所收汉字进行了“分区”处理，每区含有94个汉字/符号。这种表示方式也称为区位码。</p>
												<p>各区包含的字符如下：01-09区为特殊符号；16-55区为一级汉字，按拼音排序；56-87区为二级汉字，按部首/笔画排序；10-15区及88-94区则未有编码。</p>
												<p>（2）双字节表示</p>
												<p>两个字节中前面的字节为第一字节，后面的字节为第二字节。习惯上称第一字节为“高字节” ，而称第二字节为“低字节”。</p>
												<p>“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0)，“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。</p>
												<p>5．编码举例</p>
												<p>以GB2312字符集的第一个汉字“啊”字为例，它的区号16，位号01，则区位码是1601，在大多数计算机程序中，高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是：0xB0=0xA0+16, 0xA1=0xA0+1。</p>
												<p>
														<strong>BIG5 字符集</strong>
												</p>
												<p>1．名称的由来</p>
												<p>又称大五码或五大码，1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立，故称大五码。</p>
												<p>Big5码的产生，是因为当时台湾不同厂商各自推出不同的编码，如倚天码、IBM PS55、王安码等，彼此不能兼容；另一方面，台湾政府当时尚未推出官方的汉字编码，而中国大陆的GB2312编码亦未有收录繁体中文字。</p>
												<p>2．特点</p>
												<p>Big5字符集共收录13,053个中文字，该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字：“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。</p>
												<p>3．字符编码方法</p>
												<p>Big5码使用了双字节储存方法，以两个字节来编码一个字。第一个字节称为“高位字节”，第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9，低位字节的编码范围0x40-0x7E及0xA1-0xFE。</p>
												<p>各编码范围对应的字符类型如下：0xA140-0xA3BF为标点符号、希腊字母及特殊符号，另外于0xA259-0xA261，存放了双音节度量衡单位用字：兙兛兞兝兡兣嗧瓩糎；0xA440-0xC67E为常用汉字，先按笔划再按部首排序；0xC940-0xF9D5为次常用汉字，亦是先按笔划再按部首排序。</p>
												<p>4．Big5 的局限性</p>
												<p>尽管Big5码内包含一万多个字符，但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字，没有包含日文平假名及片假名字母。</p>
												<p>例如台湾视“着”为“著”的异体字，故没有收录“着”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中。</p>
												<p>
														<strong>GB18030 字符集</strong>
												</p>
												<p>1．名称的由来</p>
												<p>GB 18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》，是我国政府于2000年3月17日发布的新的汉字编码国家标准，2001年8月31日后在中国市场上发布的软件必须符合本标准</p>
												<p>2．特点</p>
												<p>GB 18030字符集标准的出台经过广泛参与和论证，来自国内外知名信息技术行业的公司，信息产业部和原国家质量技术监督局联合实施。</p>
												<p>GB 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位，收录了27484个汉字，覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容，填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准（GB2312，GB13000.1）兼容。</p>
												<p>3．编码方法</p>
												<p>GB 18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。双字节部分，首字节码从0×81至0×FE，尾字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀，这样扩充的四字节编码，其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE，第二、四个字节编码码位均为0×30至0×39。</p>
												<p>4．包含的内容</p>
												<p>双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有关标点符号、表意文字描述符13个、增补的汉字和部首/构件80个、双字节编码的欧元符号等。　　四字节部分收录了上述双字节字符之外的，包括CJK统一汉字扩充A在内的GB 13000.1中的全部字符。</p>
												<p>
														<strong>Unicode字符集</strong>
												</p>
												<p>1．名称的由来</p>
												<p>Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称，是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统，支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发，1994年正式公布，最新版本是2005年3月31日的Unicode 4.1.0。</p>
												<p>2．特征 </p>
												<p>Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码，以满足跨语言、跨平台进行文本转换、处理的要求。</p>
												<p>3．编码方法</p>
												<p>Unicode 标准始终使用十六进制数字，而且在书写时在前面加上前缀“U+”，例如字母“A”的编码为 004116 和字符“?”的编码为 20AC16。所以“A”的编码书写为“U+0041”。</p>
												<p>4．UTF-8 编码<br />UTF-8是Unicode的其中一个使用方式。 UTF是 Unicode Translation Format，即把Unicode转做某种格式的意思。</p>
												<p>UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字，使得双字节的Unicode能够在现存的处理单字节的系统上正确传输。</p>
												<p>UTF-8使用可变长度字节来储存 Unicode字符，例如ASCII字母继续使用1字节储存，重音文字、希腊字母或西里尔字母等使用2字节来储存，而常用的汉字就要使用3字节。辅助平面字符则使用4字节。</p>
												<p>5．UTF-16 和 UTF-32 编码<br />UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案，UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码；UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数</p>
										</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/dreamstone/aggbug/70925.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-20 21:41 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/20/70925.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>互斥</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/20/70921.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 20 Sep 2006 13:32:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/20/70921.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/70921.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/20/70921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/70921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/70921.html</trackback:ping><description><![CDATA[
		<p>互斥的几种实现方式：<br />一，忙等待互斥<br />1,禁止中断<br />2,锁变量<br />3,严格的轮换<br />4,peterson算法<br />5,Tsl<br />忙等待存在着各种各样的问题，一个最大的问题使消耗cpu，另外容器产生各种错误。而且还可能出现优先级反转问题，所以忙等待并不是很好的办法<br /><br /><u><font color="#0000ff"> 互斥2-生产者消费者（原始状态）</font></u><br /></p>
		<p>一，休眠与唤醒<br />1,经典的生产者与消费者问题<br />生产者消费者现象的原型是这样的：<br />一个生产者生产，当缓冲区满了，就自己休眠<br />一个消费者消费，当缓冲区空了，就自己休眠</p>
		<p>一个生产者生产，当生产一个产品时，就唤醒消费者（可以消费了）<br />一个消费者消费，当消费一个产品时，就唤醒生产者（可以生产了)</p>
		<p>无论是生产者，还是消费着，当被唤醒的时候不一定马上执行，还需要获得cpu</p>
		<p>◎这种设计产生了一个问题，原因是需要一个count来记录产品个数，而count的获得并没有互斥<br />例如如下情况：<br />消费者取得count=0，但是还没来得及休眠自己的时候，发生了系统进程调度，切换到生产者<br />生产者生产了一个产品后，唤醒消费者，但是这个时候的消费者并没有休眠，所以唤醒丢失<br />然后生产者继续生产，直到缓冲满了，自动休眠。<br />但是这个时候的消费者也是休眠状态，没有人来唤醒他，所以两个都一直休眠下去。</p>
		<p>解决方案：<br />提供一个标志位，当生产者发送唤醒给消费者的时候，记录下来为1，当消费者要休眠之前检查一下这个标志位，如果是1就不休眠，如果不是就休眠<br />这个方法暂时解决了问题，考虑一下。<br />如果是m个生产者，n个消费者,m,n又很大的情况下，标志位就太多了。<br />这种情况下情况下地解决办法见下一篇文章 &lt;互斥3-生产者消费者&gt;</p>
		<p>这个方案地实现程序如下:<br />#define N=100<br />int count=0;<br />void product(void){<br /> int item;<br /> while(TRUE){<br />  item=produce_item()<br />  if(count==N)sleep();<br />  insert_item(item);<br />  count=count+1;<br />  if (count==1)wakeup(consumer);<br /> }<br />}<br />void consumer(void){<br /> int item;<br /> while(TRUE){<br />  if(count==0)sleep();<br />  item=remove_item();<br />  count=count-1;<br />  if(count==N-1)wakeup(product);<br />  consume_item(item);<br /> }<br />} </p>
		<p>
				<br />
		</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/70921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-20 21:32 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/20/70921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>经典IPC问题（哲学家进餐） </title><link>http://www.blogjava.net/dreamstone/archive/2006/09/20/70920.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 20 Sep 2006 13:30:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/20/70920.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/70920.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/20/70920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/70920.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/70920.html</trackback:ping><description><![CDATA[
		<p>问题：<br />有五个哲学家，<br />每个哲学家面前有一盘面<br />每个哲学家左右各有一只筷子<br />哲学家有2个状态，思考或者拿起筷子吃饭。<br />如果哲学家拿到一只筷子，不能吃饭，拿到2只才能吃饭。</p>
		<p>一，考虑第一种自然情况：<br />解法：所有哲学家拿起一只筷子，再拿旁边的一只，如果拿不到就等，等到可以拿了再拿<br />问题：所有哲学家都拿起一只筷子，那就都吃不到饭，就是死锁<br />二，解决上边的问题<br />解法：每个哲学家先拿左边的筷子，再拿右边的筷子，如果拿不到右边的筷子，就放弃左边的筷子，等待一段时间再试<br />问题：试想所有哲学家同时拿起筷子，同时放弃，再同时拿起，同时放弃。。如此就进入了另外一种死循环<br />三，解决上边的问题：<br />解法：在上边的情况下，每次等待的时间变成随机一段时间，这样基本能解决问题，例如以太网的工作方式就是这样<br />问题：再极少数情况下，还是会出现冲突，在一些要求较高的情况，例如核电站的安全系统，这种情况试不允许出现的<br />四，最终解决方法：<br />解法：使用多个互斥信号量，每个哲学家在想取筷子前先执行mutex，然后判断一下左右的筷子是否有人用，如果没有就拿起筷子，否则就不拿筷子<br />实现程序：<br />#define N 5<br />#define Left (i+N-1)%N<br />#define Right (i+1)%N<br />#define THINKING 0<br />#define HUNGRY 1<br />#define EATING 2<br />typedef int semaphore;<br />int state(N);<br />semapore mutex =1;<br />semaphore s(N);</p>
		<p>void philosopher(int i){<br /> while(TRUE){<br />  think();<br />  take_forks(i);<br />  eat();<br />  put_forks(i);<br /> }<br />}<br />void tak_forks(int i){<br /> down(&amp;mutex);<br /> state(i)=HUNGRY;<br /> test(i);<br /> up(&amp;mutex);<br /> down(&amp;s[i]);<br />}<br />void put_forks(int i){<br /> down(&amp;mutex);<br /> state(i)=THINK;<br /> test(LEFT);<br /> test(RIGHT);<br /> up(&amp;mutex);<br />}<br />void test(i){<br /> if(state(i)==HUNGRY &amp;&amp; state(LEFT)!=EATING &amp;&amp; state(RIGHT)!=EATING){<br />  state(i)=EATING;<br />  up(&amp;s[i])<br /> }<br />}<br /></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/70920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-20 21:30 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/20/70920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>死锁</title><link>http://www.blogjava.net/dreamstone/archive/2006/09/20/70918.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 20 Sep 2006 13:29:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/20/70918.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/70918.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/20/70918.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/70918.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/70918.html</trackback:ping><description><![CDATA[
		<p>引发死锁的条件：<br />必须满足以下四种条件<br />1,互斥条件，每个资源要么已经分配给一个进程，要么就是可用的。<br />2,占有等待条件，已经得到了某个资源的进程可以再请求新的资源 <br />3,不可抢占条件，已经分配给一个进程的资源不能强制的被抢占，只能被占有他的进程显示的释放<br />4,环路等待条件，死锁发生时，系统中一定有两个或者两个以上的进程组成一环路，该环路中的每一个</p>
		<p>进程都在等待下一个进程占有的资源。</p>
		<p>处理死锁的策略：<br />1,忽略该问题，你忽略它，它也会忽略你<br />2,测试死锁并恢复，让死锁发生，检测，一旦检测到，恢复<br />3,仔细对资源进行分配，动态避免死锁<br />4,通过破坏四个死锁条件之一</p>
		<p>方法一对应的时鸵鸟算法，就是出现这种死锁的可能性很低，比如操作系统的fork，可能5年出现一次，</p>
		<p>而在这段过程中，因为硬件等其它原因肯定要重新启动机器，放弃fork损失太大，就可以忽略这种死锁</p>
		<p>，象鸵鸟一样，把头埋进沙子，当什么都没发生。</p>
		<p>方法二：检测并恢复<br />恢复方法有:<br /> 抢占恢复<br /> 回退恢复<br /> 杀死进程恢复<br />银行家算法：<br />如果有4个人(A,B,C,D)去银行贷款，银行有金额10个单位，<br />A贷款最大为6 ,A已经贷款1<br />B贷款最大为5 ,B已经贷款1<br />C贷款最大为4 ,C已经贷款2<br />D贷款最大为7 ,D已经贷款4<br />这个时候只有C的请求能通过，因为现在还有可用贷款2，只有C才能完成，然后释放更多，来让其它完成<br />这个时候如果给其它任何一个单位的贷款，那么所有的人都不能达到需求，完成。<br />银行家问题时个经典的问题，但是很少能得到实际的利用，因为每个客户自己都不知道自己需要多少资</p>
		<p>源，同时，也不知道有多少个客户。因为不停的有用户login ,logout</p>
		<p>方法四：破坏条件<br />1,破坏互斥条件，不让独占出现，<br />例如不让一个用户独占打印机，如spooling技术，让多个用户同时进入spooling<br />问题：可能在spooling中产生死锁<br />2,破坏占有等待条件<br />检测这个进程需要的所有资源是不是可用，如果可用分配，不可用的话就等待<br />问题：进程要在开始知道自己需要多少资源，这样可以使用银行家算法完成。<br />但是资源利用不是最优。<br />3,破坏不可抢占，这个实现起来最困难<br />4,破坏闭环<br />把所有资源编号，按照顺序请求</p>
		<p>饥饿：<br />与死锁很接近的时饥饿<br />如果一个打印机的使用，是通过某种算法避免死锁，但是每次都是最小文件先打印，这样就可能产生一</p>
		<p>种情况，大的文件永远不能打印，饥饿而死。</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/70918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-20 21:29 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/20/70918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>经典IPC问题（读者写者问题) </title><link>http://www.blogjava.net/dreamstone/archive/2006/09/20/70919.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Wed, 20 Sep 2006 13:29:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/09/20/70919.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/70919.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/09/20/70919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/70919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/70919.html</trackback:ping><description><![CDATA[
		<p>读者写者问题是建立在数据库访问模型上的：<br />例如飞机订票系统<br />其中多个进程想读写数据库<br />为了保证不出错需要满足一条：<br />当一个进程写的时候，所有的其它进程都不能再读和写<br />实现方法一：<br />当一个写进程到来的时候，如果有读或者写进程就不进入<br />当一个读进程到来的时候，如果没有读进程，就进入<br />也就是读可以同时，写是排它的。<br />问题：试想每个读进程持续5秒，每2秒进来一个读进程，这样写进程就永远进不来了<br />实现方法二：<br />当一个写进程来的时候，它只等待现在正在执行的读进程<br />当一个读进程进来的时候，如果有一个写进程等待，读进程不进入<br />也就是写进程优先，这样解决了问题，但是效率低下。</p>
		<p>相关的还有理发师问题；<br /></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/70919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-09-20 21:29 <a href="http://www.blogjava.net/dreamstone/archive/2006/09/20/70919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>