﻿<?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-空空也</title><link>http://www.blogjava.net/crazy/</link><description>IT技术交流平台</description><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 05:59:14 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 05:59:14 GMT</pubDate><ttl>60</ttl><item><title>汉字编码标准与识别(一)  </title><link>http://www.blogjava.net/crazy/archive/2006/04/19/41851.html</link><dc:creator>空空也</dc:creator><author>空空也</author><pubDate>Wed, 19 Apr 2006 03:54:00 GMT</pubDate><guid>http://www.blogjava.net/crazy/archive/2006/04/19/41851.html</guid><wfw:comment>http://www.blogjava.net/crazy/comments/41851.html</wfw:comment><comments>http://www.blogjava.net/crazy/archive/2006/04/19/41851.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/crazy/comments/commentRss/41851.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/crazy/services/trackbacks/41851.html</trackback:ping><description><![CDATA[代码页(Code Page)初识  


本节是根据以下文章编写出来的，建议认真研读这些专家的高论。  
参考1 &lt;&gt; 张 轴 材   
&lt;&lt;计算机世界&gt;&gt;周报 97-1-17  
参考2 &lt;&lt;张轴材 谈汉字交换码标准建立历程&gt;&gt; &lt;&lt;计算机世界&gt;&gt;周  
报记者 黄伟敏 肖春江 99-8-30  
参考3 &lt;&lt;中文平台把住“根”留住&gt;&gt; 吴健 &lt;&lt;中国计算机报&gt;&gt;  
出版日期：1998-12-21　总期号：348　本年期号：51  
参考4 &lt;&lt;为种种UNIX中文平台号脉&gt;&gt; 孙玉芳 &lt;&lt;中国计算机用户&gt;&gt;  
出版日期：1998-07-06　总期号：323　本年期号：26  
参考5 CJK.INF:ftp://ftp.ora.com/pub/examples/nutshell/ujip/  
doc/cjk.inf  

因为本人只是业余水平，不是专家，对于参考资料中许多术语还不  
理解，更没有见过任何一种标准的正式文本，错误和模糊之处再所  
难免。同时，因为国家有关部门对于宣传，推广和贯彻国家标准方  
面力度不够，致使象我这样的初学者或初涉该领域的小企业因信息  
资源不足而处于不利的竞争地位。  
ASCII制订的时候，并没有考虑对多语种，特别是对象中国汉字这样  
的象形文字的支持。为此后来又提出了不少解决方案，其中代码页  
体系(ISO2022)是现在普遍实行的方案，而ISO10646/GB13000/Unicode  
是今后发展的方向。  
中国的汉字编码标准GB2312是7bits标准，具体说是双7位字节标准。  
而ASCII是单7位字节标准,计算机怎么区分呢?一种是在第八位置"1",  
提示计算机转入双字节编码,这是最常见的一种实现,也叫EUC  
(Extended Unix Code)编码.另一种是用特殊标记提示计算机转入双  
字节编码,如HZ编码就是用开始，用结束的块标识双字节编码区.它们  
都是GB2312的一种实现.对象中国汉字这样的象形文字体系，代码页  
是根据各个国家，地区或行业标准，按照EUC方式编码。代码页向下  
兼容ASCII，是一种不等长编码。会带来代码的复杂性，同时还会引  
起因代码页切换而带来的乱码问题。  
Unicode是一种多字节等长编码。ISO10646/GB13000/Unicode现已在  
UCS2上实现一致，也就是已实现双字节编码标准。下面所讨论的  
ISO10646/GB13000/Unicode，就只是指UCS2这种情况。Unicode对  
ASCII采取前面加"0"字节的策略实现等长兼容。如"A"的ASCII码为0x41,  
Unicode码就为0x00,0x41。  
这里主要从国家标准(GB)系列入手了解Unicode。如果不是看了参考5  
(英文)，我还不知道国家关于汉字编码的标准如此之多。中国人居然  
要从英文资料里了解汉字编码标准，实在是很无奈的事情。  
常用中文编码标准 资料来源:CJK.INF  
GB2312-1980(GB0)(简体) GB7589-1987(GB2)(简体)  
GB7590-1987(GB4)(简体) GB13000-1993  
GB6345.1-1986(GB0修正)  
GB8565.2-1988(GB8,GB0扩充)  
GB/T12345-90(GB1)(繁体) GB/T13131-9X(GB3)(繁体)  
GB/T13132-9X(GB5)(繁体)  


其中横向表示字符集系列。纵向表示各个系列的发展标准。其中  
GB2312是基本集，也就是目前最常用的标准。GB7589/GB7590是扩展  
集，使用时可能不能和GB2312共存，需要切换使用。GB7589/GB7590  
是按部件(部首)和笔顺(笔画)排列，但具体有什么字，怎么排列，  
用在什么领域，不清楚。GB2312系列经过两次修正和扩充，已和原  
始的GB2312-1980标准有些不同(参考5)。因为没有标准文本，不知  
道正在使用的字体是属于哪个标准。根据最新的Unicode3.0，国家  
标准最新的是GB16500-95 ，更不知是哪个系列的了。ISO/IEC 10646  
等同于GB13000-1993/JIS0221-1995/KSC5000-1995这些国家标准。  
制订的目标是包容各语种的文字，其中以汉字最多(Unicode2.0有  
20902个汉字)。关于标准的特点可以看参考1，制订过程中的风风  
雨雨，可以看参考2。总之，这是一个我们国家参与并占主导地位  
的国际标准。  
GBK是GB2312向GB13000过渡的一个中间产物。它是GB2312的一次大  
的扩展，编码向下兼容GB2312的EUC编码，字汇(字符集)和GB13000  
相同，是GB2312的3倍。所以说GBK也包含BIG5，Shift-JIS，KSC的  
字汇。注意只是包含字汇，而编码与原始的标准是不同的。在具体  
应用中，用GBK字体就可以同时显示GB2312，BIG5，Shift-JIS，KSC  
的字符串。但除了GB2312字符串，其它都要转换(convert)。  
因为语焉不详，不清楚制订GBK时是谁占主导地位。因为有些英文资  
料说是Microsoft制订了GBK，而国家方面也没有进行说明。目前从  
这些参考资料只知道，94年ISO/IEC 10646发布后，Microsoft开发  
Windows95中文版，要制订中文扩展编码。96年《汉字扩展内码规范》  
GBK发布(参考1~3)。按标准发布比制定晚一年推算，这是95年的事。  
Windows95及后续版本中文版支持GBK。  
GB2312的EUC编码范围是第一字节0xA1~0xFE(实际只用到0xF7)，第  
二字节0xA1~0xFE。GBK对此进行扩展。第一字节为0x81~0xFE，第二  
字节分两部分，一是0x40~0x7E，二是0x80~0xFE。其中和GB2312相  
同的区域，字完全相同。扩展部分大概是按部件(部首)和笔顺(笔画)  
从GB13000中取出再排列入GBK中。因此GBK并不是GB13000，虽然两者  
字汇相同，但编码体系不同。一个是ISO2022系列不等长编码，一个  
是等长编码，并且编码区域也不同。注意到GBK实际上不是国家标准。  
在此之前有一个GB2312基本集，在它之上是一个技术更先进的GB13000。  
GBK只是一种过渡和扩展规范。所以在Unicode里有GB2312-&gt;Unicode,  
GB12345-&gt;Unicode的转换表格，而没有GBK-&gt;Unicode转换表格。只有  
Microsoft制作的Code Page 936(CP936.TXT)可以算作GBK-&gt;Unicode  
转换表格。但要注意这是一个商业公司制作的文件，而不是国家或  
国际标准组织制作的，有可能与标准有不一致的地方。最近在方正字  
体网站发现一些有用的标准文件,有兴趣可以下载看看.但要注意  
Gbk-big5.tab和Gb-big5.tab这两个文件有点瑕疵.  
http://www.founderpku.com/fontweb/download/Gbk-big5.tab  
http://www.founderpku.com/fontweb/download/Gb-big5.tab  
http://www.founderpku.com/fontweb/gb2312.htm  
http://www.founderpku.com/fontweb/gbk.htm  
在使用这些转换表制作其它标准的相互转换表，会和传统的转换表  
有所不同。如用GBK&lt;=&gt;Unicode&lt;=&gt;BIG5制作GBK&lt;=&gt;BIG5转换表，就  
会和传统的GB&lt;=&gt;BIG5转换表有所不同。主要是汉字有简体和繁体。  
前者是GBK(中的繁体字)&lt;=&gt;BIG5(繁体字)，后者是GB(简体)&lt;=&gt;BIG5(繁体)。  
还有就是对一些制表符选用不同。对汉字繁简转换有兴趣的读者，可以看  
http://www.basistech.com/articles/c2c.html  
http://www.cjk.org  




内码与字体的关系  

虽然没有标准文本，但还是可以大致了解常用标准有那些字。TLC4.0的  
字库带有GB2312，GB12345，BIG5，GBK标准的pcf字体。可以用xfd实用  
程序查看。在http://www.debian.org/chinese下有一个16点阵的Unicode  
的pcf字体。如果安装了FreeType，可以使用xmbdfed软件查看TTF字体。  
如果用MS WORD，可能会更简单些。  
在日常使用中，我们实际上熟悉的是字码(内码).在中文WIN9X下,我们输  
入一个双八位字节,就得到一个汉字,就会认为这双八位字节就是对应这  
样的字形.这是错误的.其实内码对于字库来说,只是查找字形的索引.如  
果换另一个编码标准的字体，同一个字符串就会呈现不同的字形，也就  
是乱码。我见过GB2312,BIG5和ISO10646/GB13000的TTF字库.对于操作系  
统和应用程序来说,最喜欢的自然是ISO10646/GB13000的TTF字库了.因为  
这时只需提供一套代码和一套字库,修改外部配置文件,就可以用在不同的  
语种环境.这就是国际化和本地化.其中有个技巧就是ISO10646/GB13000的  
TTF字库可以在使用时可以通过重映射变成其它标准的字库.这时需要的是  
GBK-&gt;Unicode,Big5-&gt;Unicode这些转换表.一个系统要升级支持Unicode3.0,  
也难也不难.简单的地方是只需修改转换表就行了(如windows
ls*.*).  
难的是要升级字库.开发字库是很困难的,可以到方正字库网站看看开发字  
库的步骤.WIN9X使用的是北京中易公司的TTF字库,MS是不可能开发一套中  
文字库的.我所见过的ISO10646/GB13000的TTF字库,最新的是99年版,Unicode2.1 
,  
方正字库.要想见到Unicode3.0的所有字形,也只有等这些专业字库开发商  
做出来才行.如果现在就想看,只有问张轴材了.因为每通过一次新标准,中  
国方面就要提供所有汉字的48x48高精密字形.使用TTF字体始终是诱人的话  
题。但现在了解不多，只能简单谈谈从TTF字体生成bdf/pcf字体的问题。  
因为现在中文pcf字体很少，只有宋体，仿宋，黑体，楷体四种。要想有更  
多的字体，有个取巧的方法就是使用freetype库。用ttftobdf程序生成bdf  
字体，再用bdftopcf程序生成pcf字体。但这种方法生成的字体缩放后比较  
难看，而且不宜控制。这可能是ttf-&gt;bdf的转换过程丢失了信息，高宽比  
也和标准的不一样。机器生成的东西就是机械，是不能和手绘的字体相比  
的。同时，因为TTF技术已成熟，所以也没有必要继续开发更多的pcf字体。  
X window将接受和大量使用TTF字体。而pcf字体今后主要用在标准字型  
（如宋体），小点阵，网上快速下载传输方面。只有实际在X Window下用  
过Unicode和TTF的字体，才会体会到使用Unicode和TTF，既是一种能力，  
也是一种负担。因为不论是什么格式的字体文件，最后在使用时都转化为  
内存里固定点阵字体。如果是16x16点阵，一个汉字就用32字节。Unicode3.0  
有27786个汉字,至少需要868kb的内存。如果要中文英文美观一致，还得装  
载大量的中文字体，所需内存可想而知。如果再使用TTF，还需要另一块内  
存来运算和存储。因此，就算X Window提供了字体cache和deferglyphs，  
还是于事无补。而我们常用的汉字其实很少。根据统计，常用汉字的频率，  
前165个汉字频率和&gt;50%，前1000个汉字频率和&gt;95%；按小学教学经验，识  
字900个左右，基本可以读书，看报，写作文；按小学教学大纲，小学毕业  
识字2500字；GB2312的一级字库的频率和已&gt;99%。我想我自己识字大约为  
4000~5000，对比Unicode的汉字，好象一个文盲:-)。因此是用GB2312，还  
是用GB13000，真是一个两难决择，我们也要为我们的选择付出代价。  
最后通过内码与字体的关系，讨论UTF8的作用。  
UTF8是现有ASCII系统转向Unicode系统的一个过渡解决方案。UTF8是保证  
ASCII兼容性，再向大字符集方向扩展。这是Unicode推荐的方案。但是因  
为解决问题的角度不同，对现有的中文系统不是好的解决方案。  
CJK字符编码标准目前都为一字/两字节。中文在UCS2中的编码范围是  
U+4E00~U+9FFFF。按照UTF8的编码规则，为一字/三字节，增加1/3的空间。  
同时和现有的CJK系统不兼容。CJK系统要使用UTF8，先转换为UCS2，再转换  
为UTF8。后一步简直是多此一举。因为从字库的角度看，字的编码只是字形  
在字库中的索引。UTF8是变长码，不能直接做索引，需要转换为UCS2才能使  
用字库。  
随着GUI的发展，字库逐渐转向TTF。TTF字库的编码标准，有GB2312/GB2312  
的EUC标准；BIG5标准；ISO10646标准。没有见过UTF8的TTF，也不知道CJK  
这些国家有哪些系统使用了UTF8编码。  
目前Unicodde有一个特点就是内核代码(CoreCode)。用户表面上可以继续使  
用原有的编码标准，系统内部使用UCS2进行运算和操作。系统使用用户可改  
变的标志或模块，以识别用户需要的编码标准，然后进行转换。这样，系统  
只需提供一套ISO10646的TTF，不修改内部代码，就可以为多个用户同时提供  
中文，日文，韩文的支持。Windows95及后面的中文版就是采用这个方案。现  
有的X window的TTF服务器，X-TT和xfsft也可以使用这个方案。  
前者在TurboLinux中文版里得到了实现，后者我试验过，效果还不错。还有  
一个有趣的现象，就是红旗Linux1.1版所带的那个12点阵的pcf字体  
/usr/X11R6/lib/X11/fonts/misc/gb12st.pcf.gz。这已不是严格意义上的  
GB2312编码的字库了。用xfd实用程序查看，好象是从Unicode编码的TTF字体  
转换来的，有些GBK的字，可惜太少。如果他们能出些GBK编码标准的pcf字体  
就好了。  
CJK系统转向UCS2与ASCII系统转向UTF8，两者的代码修改量是相当的。只是前  

者多了转换表，需要内存多些。不过ASCII系统使用UCS2，需要增加50%的空间。 
  
目前计算机里大多数还是ASCII的信息，看来这也是一个问题。  
<img src ="http://www.blogjava.net/crazy/aggbug/41851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/crazy/" target="_blank">空空也</a> 2006-04-19 11:54 <a href="http://www.blogjava.net/crazy/archive/2006/04/19/41851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JSP实现的一个日历程序</title><link>http://www.blogjava.net/crazy/archive/2006/04/19/41850.html</link><dc:creator>空空也</dc:creator><author>空空也</author><pubDate>Wed, 19 Apr 2006 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/crazy/archive/2006/04/19/41850.html</guid><wfw:comment>http://www.blogjava.net/crazy/comments/41850.html</wfw:comment><comments>http://www.blogjava.net/crazy/archive/2006/04/19/41850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/crazy/comments/commentRss/41850.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/crazy/services/trackbacks/41850.html</trackback:ping><description><![CDATA[
		<!-- File name:calendar.jsp -->
		<!-- 显示任意年、月的日历，可选择不同的年、月。author:wildfield --> 
&lt;%@ page language="java" import="java.util.*" %&gt; 
&lt;%! String year; 
   String month; 
%&gt; 
&lt;% month=request.getParameter("month"); 
   year =request.getParameter("year"); 
%&gt; 
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><title>日</title><script language="JavaScript"><!-- 
function changeMonth() 
{ 
 var mm="calendar.jsp?month="+document.sm.elements[0].selectedIndex+"&year=" 
+<%=year%>; 
 window.open(mm,"_self"); 
} 
//--></script></head> 
&lt;%! String days[]; %&gt; 
&lt;% 
 days=new String[42]; 
 for(int i=0;i&lt;42;i++) 
  { 
   days[i]=""; 
  } 
%&gt; 
&lt;% 
 Calendar thisMonth=Calendar.getInstance(); 
  if(month!=null&amp;&amp;(!month.equals("null"))) 
   thisMonth.set(Calendar.MONTH, Integer.parseInt(month) ); 
  if(year!=null&amp;&amp;(!year.equals("null"))) 
   thisMonth.set(Calendar.YEAR, Integer.parseInt(year) ); 
  year=String.valueOf(thisMonth.get(Calendar.YEAR)); 
 month=String.valueOf(thisMonth.get(Calendar.MONTH)); 
 thisMonth.setFirstDayOfWeek(Calendar.SUNDAY); 
 thisMonth.set(Calendar.DAY_OF_MONTH,1); 
 int firstIndex=thisMonth.get(Calendar.DAY_OF_WEEK)-1; 
 int maxIndex=thisMonth.getActualMaximum(Calendar.DAY_OF_MONTH); 
 for(int i=0;i<maxindex;i++) {="" days[firstindex+i]="String.valueOf(i+1);" }="" %=""><body onbeforeunload="RunOnBeforeUnload()"><form name="sm" method="post" action="calendar.jsp"> 
   &lt;%=year%&gt;年  &lt;%=Integer.parseInt(month)+1%&gt;月 
<table border="0" width="168" height="81"><div align="center"><tr><th width="25" height="16" bgcolor="#FFFF00"><font color="red">日</font></th><th width="25" height="16" bgcolor="#FFFF00">一</th><th width="25" height="16" bgcolor="#FFFF00">二</th><th width="25" height="16" bgcolor="#FFFF00">三</th><th width="25" height="16" bgcolor="#FFFF00">四</th><th width="25" height="16" bgcolor="#FFFF00">五</th><th width="25" height="16" bgcolor="#FFFF00"><font color="green">六/th&gt; 
  </font></th></tr> 
&lt;% for(int j=0;j&lt;6;j++) { %&gt; 
 <tr> 
      &lt;% for(int i=j*7;i&lt;(j+1)*7;i++) { %&gt; 
     <td width="15%" height="16" bgcolor="#C0C0C0" valign="middle" align="ce &#xD;&#xA;nter"><a href="jump.jsp?year=&lt;%=year%&gt;&amp;month=&lt;%=Integer.parseInt(month)+1%&gt;&amp;d &#xD;&#xA;ate=&lt;%=days[i]%&gt;" target="main"><![CDATA[<%=days[i]%>]]&gt;</a></td> 
    &lt;% }  %&gt; 
  </tr> 
&lt;% }  %&gt; 
</div></table><table border="0" width="168" height="20"><tr><td width="30%"><select name="month" size="1" onchange="changeMonth()"><option value="0">一月</option><option value="1">二月</option><option value="2">三月</option><option value="3">四月</option><option value="4">五月</option><option value="5">六月</option><option value="6">七月</option><option value="7">八月</option><option value="8">九月</option><option value="9">十月</option><option value="10">十一月</option><option value="11">十二月</option></select></td><td width="28%"><input type="text" name="year" value="&lt;%=year%" /> size=4 maxlength 
=4&gt;</td><td>年</td><td width="28%"><input type="submit" value="提交" /></td></tr></table></form><script language="JavaScript"><!-- 
  document.sm.month.options.selectedIndex=<%=month%>; 
//--></script></body></maxindex;i++)></html><img src ="http://www.blogjava.net/crazy/aggbug/41850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/crazy/" target="_blank">空空也</a> 2006-04-19 11:51 <a href="http://www.blogjava.net/crazy/archive/2006/04/19/41850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>