字符编码教案

2024-05-04

字符编码教案(共8篇)

篇1:字符编码教案

ASCII

ASCII码是7位编码,编码范围是0×00-0×7F,ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。其中0×00-0×20和0×7F共33个控制字符。

只支持ASCII码的系统会忽略每个字节的最高位,只认为低7位是有效位。HZ字符编码就是早期为了在只支持7位ASCII系统中传输中文而设计的编码。早期很多邮件系统也只支持ASCII编码,为了传输中文邮件必须使用BASE64或者其他编码方式。

GB2312

GB2312是基于区位码设计的,区位码把编码表分为94个区,每个区对应94个位,每个字符的区号和位号组合起来就是该汉字的区位码。区位码一般用10进制数来表示,如1601就表示16区1位,对应的字符是“啊”。在区位码的区号和位号上分别加上0xA0就得到了GB2312编码。

区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分成两级:第一级是常用汉字计 3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。一级汉字是按照拼音排序的,这个就可以得到某个拼音在一级汉字区位中的范围,很多根据汉字可以得到拼音的程序就是根据这个原理编写的。

GB2312字符集中除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。可以用繁体汉字测试某些系统是不是只支持GB2312编码。

GB2312的编码范围是0xA1A1-0×7E7E,去掉未定义的区域之后可以理解为实际编码范围是0xA1A1-0xF7FE。

EUC-CN可以理解为GB2312的别名,和GB2312完全相同。

区位码更应该认为是字符集的定义,定义了所收录的字符和字符位置,而GB2312及EUC-CN是实际计算机环境中支持这种字符集的编码。HZ和ISO- 2022-CN是对应区位码字符集的另外两种编码,都是用7位编码空间来支持汉字。区位码和GB2312编码的关系有点像 Unicode和UTF-8。

GBK

GBK编码是GB2312编码的超集,向下完全兼容GB2312,同时GBK收录了Unicode基本多文种平面中的所有CJK汉字。同 GB2312一样,GBK也支持希腊字母、日文假名字母、俄语字母等字符,但不支持韩语中的表音字符(非汉字字符)。GBK还收录了GB2312不包含的汉字部首符号、竖排标点符号等字符。

GBK的整体编码范围是为0×8140-0xFEFE,不包括低字节是0×7F的组合。高字节范围是0×81-0xFE,低字节范围是0×40-7E和0×80-0xFE。

低字节是0×40-0×7E的GBK字符有一定特殊性,因为这些字符占用了ASCII码的位置,这样会给一些系统带来麻烦。

有些系统中用0×40-0×7E中的字符(如“|”)做特殊符号,在定位这些符号时又没有判断这些符号是不是属于某个 GBK字符的低字节,这样就会造成错误判断。在支持GB2312的环境下就不存在这个问题。需要注意的是支持GBK的环境中小于0×80的某个字节未必就是ASCII符号;另外就是最好选用小于0×40的ASCII符号做一些特殊符号,这样就可以快速定位,且不用担心是某个汉字的另一半。Big5编码中也存在相应问题。

CP936和GBK的有些许差别,绝大多数情况下可以把CP936当作GBK的别名,

GB18030

GB18030编码向下兼容GBK和GB2312,兼容的含义是不仅字符兼容,而且相同字符的编码也相同。GB18030收录了所有Unicode3.1中的字符,包括中国少数民族字符,GBK不支持的韩文字符等等,也可以说是世界大多民族的文字符号都被收录在内。

GBK和GB2312都是双字节等宽编码,如果算上和ASCII兼容所支持的单字节,也可以理解为是单字节和双字节混合的变长编码。GB18030编码是变长编码,有单字节、双字节和四字节三种方式。

GB18030的单字节编码范围是0×00-0×7F,完全等同与ASCII;双字节编码的范围和GBK相同,高字节是0×81-0xFE,低字节的编码范围是0×40-0×7E和0×80-FE;四字节编码中第一、三字节的编码范围是0×81-0xFE,二、四字节是0×30-0×39。

Windows中CP936代码页使用0×80来表示欧元符号,而在GB18030编码中没有使用0×80编码位,用其他位置来表示欧元符号。这可以理解为是GB18030向下兼容性上的一点小问题;也可以理解为0×80是CP936对GBK的扩展,而GB18030只是和GBK兼容良好。

unicode

每一种语言的不同的编码页,增加了那些需要支持不同语言的软件的复杂度。因而人们制定了一个世界标准,叫做unicode。unicode为每个字符提供了唯一的特定数值,不论在什么平台上、不论在什么软件中,也不论什么语言。也就是说,它世界上使用的所有字符都列出来,并给每一个字符一个唯一特定数值。

Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,它不能覆盖全部历史上的文字,也不能解决传输的问题 (implantation head-ache’s),尤其在那些基于网络的应用中。已有的软件必须做大量的工作来程序16位的数据。

因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在 UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分,例如,在UTF-8和ASCII中,“A”的编码都是0×41.

UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指UTF-16。在讨论Unicode时,搞清楚哪种编码方式非常重要。

UTF-8

Unicode Transformation Format-8bit,允许含BOM,但通常不含BOM。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。UTF-8编码的文字可以在各国支持UTF8字符集的浏览器上显示。如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。

GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBD大。

GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:

GBK、GB2312--Unicode--UTF8

UTF8--Unicode--GBK、GB2312

对于一个网站、论坛来说,如果英文字符较多,则建议使用UTF-8节省空间。不过现在很多论坛的插件一般只支持GBK。

篇2:字符编码教案

字符编码钓鱼的利用脚本安全

链接中的Url地址可以通过不同编码将字符形似的域名指向另一个地址:如ɴuanyue.com地址,点击后实际指向的地址是:www.xn--uanyue-93c.com/,恶意攻击者可通过注册这样的域名,利用错觉达到钓鱼的目的,请注意复制和点击的链接。

篇3:字符编码教案

关键词:编码方式,字符集,UTF-8,记事本,误判

1 引言 (Introduction)

在Windows操作系统环境下, 新建一个记事本文档, 输入“联通”二字, 保存并退出, 再次打开该文件时, 会发现“联通”二字显示为乱码。该现象普遍存在于中文WIN2000、2000 Pro、2000Server、XP、WIN7、WIN8、WIN8.1等系统中, 这是Windows记事本自身存在的一个Bug, 至今仍未解决。到底是什么原因导致了该现象的存在呢?

这是计算机编码方式问题导致的。Windows记事本保存文件有4种编码类型, 分别为ANSI、Unicode、Unicode bigendian、UTF-8, 默认保存编码类型为ANSI。输入“联通”二字后, 记事本通过ANSI编码方式对其进行存储, 再次打开该文件时, 记事本错误的判断该文件是由UTF-8进行编码的, 便通过对应的解码方式进行解码 (Decoding) 。由于ANSI和UTF-8编码方式和所属字符集的差异, 最终呈现出人们看到的乱码。本文针对该问题进行研究。

2 各种编码方式特点及其发展 (Characteristics anddevelopment of various encoding)

2.1 关于ASCII码与扩展字符集

ASCII码是在1947年由美国国家标准学会 (AmericanNational Standard Institute, ANSI) 制定的美国标准信息交换代码 (American Standard Code for InformationInterchange, ASCII) , 使用7个二进制位 (占一个字节, 首位补0) , 共128种组合表示所有大小写字母[1]。包括数字0到9, 标点符号以及在美式英语中使用的特殊控制符号, 属单字节字符编码系统。

ASCII码无法表示一些欧洲国家的常用字符, 如英镑符号 (£) 。因此, 1981年在标准ASCII码的基础上, 使用没有用到的最高码位, 共8个二进制位, 扩展了128到255 (0x80-0xff) 共128种状态的字符, 称为扩展字符集。

2.2 关于GB2312、GBK、GB18030编码

标准ASCII码和扩展字符集仍然不能满足世界各地的需要, 所以不同国家制定了自己特有的字符集。如中国, 以ASCII码为基础制定了GB2312编码集。GB2312规定小于127的沿用ASCII码, 当两个大于127的字符连在一起时表示一个汉字, 这样组合出6763个简体汉字、682个符号[2]。同时将数字、标点、字母都重新编排了占两个字节的编码, 这就是半角全角的问题。1995年又以GB2312为基础扩展制定了GBK标准。GBK沿用GB2312的标准, 但要求连在一起的两个字符只要第一个大于127就表示一个汉字。为了方便少数民族, 后又制定了GB18030编码。

从ASCII、GB2312到GBK再到GB18030, 都是向下兼用的, 即同一个字符在这些方案中总有相同的编码, 后来的标准支持更多的字符, 从ANSI派生出的字符集都称为ANSI字符集。

2.3 关于Unicode编码

世界各地不同语言都制定了自己的字符集, 种类繁多, 国际交流中需要转换字符集极其不便[3]。因此, 国际标准化组织 (International Organization for Standardization, ISO) 开展了ISO/IEC 10646项目, 全称“Universal Multiple-Octet Coded Character Set”, 简称UCS (双字节称为UCS-2, 四字节称为UCS-4) , 俗称Unicode字符集。Unicode字符集使用16bits表示一个字符, 0—127的ASCII码也扩展为两个字节, 用0-0x10FFFF来映射这些字符, 可表示65536个字符, 几乎将世界上所有语言的常用字符收录其中。标准的Unicode编码称为UTF-16, 为了能使双字节的Unicode在单字节处理的系统上正确传输, 便使用类似MBCS的方式对Unicode进行编码, 利用保留字符制定了三套编码方式, 分别为UTF-8、UTF-16、UTF-32。

2.4 关于UTF-8编码

UTF-8是用1到4个字节编码Unicode的可变长度字符编码, 又称万国码。UTF-8用一个字节来表示字母和一些键盘上的符号, 当用多字节表示时UTF-8设定了标志位。

当要表示的内容是7位的时候就用一个字节存储, 形如0xxxxxxx。首位0为标志位, 剩下码位正好可以表示ASCII码0—127的内容。当要表示的内容在8到11位的时候就用两个字节存储, 形如110xxxxx 10xxxxxx。第一个字节的110和第二个字节的10为标志位。当要表示的内容在12到16位的时候就用三个字节存储, 形如1110xxxx 10xxxxxx10xxxxxx。第一个字节的1110和第二、三个字节的10为标志位, 其余的码位用来表示汉字。

UTF-8以8位为单元对UCS-2编码模板, 详见表1。

UTF-8以8位为单元对UCS-4编码模板, 详见表2。

2.5 关于BOM问题

新建空文本文档分别以ANSI、Unicode、Unicode bigendian、UTF-8编码格式存储, 通过软件Winhex解析文件, 发现除ANSI编码外, 其他编码方式都存在标志头字符, 即根据不同的编码方式在其文件头添加规定的标志字符用以区分。Unicode规范中称该标志字符为字节顺序标志 (ByterOrder Mark, BOM) , 俗称标签。Winhex解析各种编码类型的BOM, 详见表3。

3 软件对文件编码方式误判的研究 (Researchsoftware for document encoding misjudgment)

在上述编码知识的基础上, 下面针对记事本不能正常显示“联通”二字进行分析。

3.1 记事本不能正常显示“联通”二字的研究

新建文本文档1, 输入“联通”二字, 保存后退出, 记事本是以默认存储的编码方式 (即ANSI) 进行保存的。再次打开后会发现显示为乱码, 点击文件-另存为, 发现该文件编码方式显示为UTF-8, 说明记事本认为这是一个UTF-8编码的文件。如果再新建一个文本文档2, 文件-打开, 选中文本文档1后, 编码方式选择ANSI, 打开后便能正确显示“联通”二字, 或者在新建文本文档1中输入“联通”二字后, 另存时编码选择为UTF-8, 保存后退出, 再次打开也能正常显示“联通”二字。由此可以推断这是编码问题导致的。

新建文本文档, 输入“联通”二字保存后, 将文件导入Winhex查看其十六进制编码, 发现为C1 AA CD A8 (H) , 由此可以确定记事本是将“联通”二字按照ANSI编码方式进行存储的, 因此再次打开时选择ANSI编码, 记事本将按照对应方式解码, “联通”二字便可以正常显示了。因此, 若首次将“联通”二字保存为UTF-8编码方式, 记事本按照UTF-8解码 (Decoding) 时便能正确显示了。

双击打开文件, 内容显示为乱码, 是因为记事本将ANSI编码存储的文件用UTF-8编码对应的解码方式进行了解码, 致使错误产生。“联通”二字的ANSI编码为C1 AA CDA8, 如图1所示, 对应二进制代码为1100 0001 (C1) , 10101010 (AA) , 1100 1101 (CD) , 1010 1000 (A8) 。

对于“联”字, 第一二个字节、第三四个字节的起始部分都是“110”和“10”, 正好符合UTF-8规则里的双字节模板。再次打开文件时, 记事本其实根据二进制代码错误判断得出这是一个UTF-8编码的文件, 根据UTF-8规则去掉第一个字节的110和第二个字节的10, 得到有效代码为1101010, 补上前导0后为0000 0000, 0110 1010, 即006A (H) 在Unicode字符集中对应小写字母j。同理, “通”字也按此解码得到0368 (H) , 在Unicode字符集中该编码不对应任何字符, 因此致使记事本显示为乱码。

3.2 对记事本IsTextUTF8函数的研究

那么记事本究竟通过何种方式来判断文件的编码方式呢?

猜测是根据有无BOM判断的。早期一些软件并不在文件头添加相应的BOM文件, 因此软件不能单纯通过BOM进行判断, 不得不进行模糊判断。通过分析记事本的源代码, 可知记事本是通过nputf.c文件中的函数INT IsTextUTF8 (LPSTRlpstrInputStream, INT iLen) 进行判断的, 对此函数作出如下分析。

//基于UTF-8双字节模板编码方式进行判断

//若为UTF-8编码该函数返回真, 若判断只属于前128个字符返回假, 认为是ASCII码

INT IsTextUTF8 (LPSTR lpstrInputStream, INTiLen) {

DWORD cOctets; //cOctets若是UTF-8, 控制以10开头位段数

UCHAR chr;//一个字节长度的字符类型chr

BOOL bAllAscii= TRUE;//若为真将按照ASCII码标准进行编码

INT i; cOctets= 0;

for (i=0; i < iLen; i++) {

chr= * (lpstrInputStream+i) ;

if ( (chr&0x80) != 0) bAllAscii= FALSE;//0x80对应二进制是1000 0000, 因为ASCII码只用了7位, 首位为零, 若是ASCII码, 该判断值为假

if (cOctets == 0 {//当字符不全由ACSII组成时

if (chr >= 0x80) {//若大于0x80, 说明在ASCII码之外

do {

chr <<= 1;//向左移位, 用以判定是否符合UTF-8开头110 1110…的方式

cOctets++;//10开头位段数加一

}

while ( (chr&0x80) != 0) ;

cOctets--;//临界处理

if (cOctets == 0) return FALSE;//若不符合形式11xxxxxx返回假

}

}

else {

if ( (chr&0xC0) != 0x80) {//若八位组编码符合10xxxxxx形式返回真, 否则返回假

return FALSE;

}

cOctets--;//处理下一个八位组编码

}

}//文本统计判断结束

if (cOctets >0) {

return FALSE;//若后边的八位组与首个八位组首位1的个数不满足UTF-8的规律返回假

}

if (bAllAscii) {return FALSE;//若全部满足符合ASCII码, 均小于128, 返回假

}

return TRUE;//若不满足上述情况返回真

}

由此可以看出, 记事本正是通过UTF-8标志位的特殊形式进行判断的, 证实了“联通”二字不能正常显示原因的推断。由此, 可以得出结论“联通”二字不能正常显示是因为误将ANSI编码方式判断为UTF-8编码, 致使解码错误导致无法在相应字符集找到字符, 故显示为乱码。

4 更多不能被正确解码的汉字 (More characterscan not be correctly decoded)

综上所述, 是否符合研究得到形式的字符都会被错误解码呢?

根据误判原因和UTF-8双字节模板特点, 发现16进制形式汉字字符, 只要第一个字符为C或D, 第三个字符为A或B的, 都将被误解码。

符合上述特点的汉字组成的高频词语, 如“笑脸”“谢谢”“两辆”“拉力”等, 它们不能正确的显示会使人们产生困惑。在这些汉字之后继续输入其他汉字即可正常显示, 而全文仅由符合上述特点的汉字组成便会显示为乱码。这是由于INT IsTextUTF8 (LPSTR lpstrInputStream, INT iLen) 函数是基于统计判断的, 一篇文章只要有一组不符合UTF-8编码形式软件便会认为文本是ANSI编码。

5 结论 (Conclusion)

本文通过分析发现, 汉字文本显示为乱码是软件对文件编码方式的错误判断造成的, 发现了更多记事本不能正确显示的汉字, 由这些汉字组成的高频词语不能正确的显示会使人们产生困惑。对软件如何能正确判断文件的编码方式, 还需要具体的程序来实现。

参考文献

[1]冯灵清, 杨怀卿, 刘宇晶.常用编码方式及其转换格式[J].计算机时代, 2012 (1) :33-35.

[2]张晓培, 李祥.从Unicode到GBK的内码转换[J].微计算机应用, 2006, 27 (6) :757-759.

篇4:字符编码教案

多字节编码由来

我们先来看看最常用的,最小字符集是ascii,对应的二级制描述是00-7F 。也是我们计算机使用最早通用的字符集。前期几乎可以表示所有所有英文字符。后来,我们发现想用此表示中文字符。发现远远不够了。常见中文就有7000多个字符。ascii码就只有128字符,只有0-127编码位置。因此,我们想法就是,怎么样做更大字符集,并且保证兼容ascii编码。要支持更多字符,选择更大字符集。我们只能用多个字节来描述一个字符了。一般做法是:每个字节值都大于>7F,如果是多个字节,那么就是:[>7F][>7F]。 这样编码,保证很好的与ascii区分开,有扩大了字符集。想gb2312范围在[0xA1-0xF7][0xA1-0xFE](中间很多没有填满),它完全保证所有字节在A0之上,也就完全满足在7F之上了。

GBK编码漏洞缘由

通过上面的分析,我们知道gb2312编码是很好的跟ascii码分开了。 那么我们看看,GBK编码呢,它是完全兼容gb2312(就是说在gb2312字符集中每个字符位置,与gbk字符集里面位置完全一致,而且包含于gb2312),但是,它有2万多个字符。从上面看,只能选择往下排序了。 就是从A1A0往下排了,我们发现它编码实际范围是:[0x81-0xFE]([0x40-0x7E|0x80-0xFE] ),我们发现由2个字节组成,首字节范围在7F之上,而第2个字节,有一部分在0×40-0x7E了。这就是导致bug原因。我们看看下面例子吧!

从ASCII码表中,我们知道包含字符有:“A-Za-z@[]^_`{|}~”,一共有63字符呢。

选择gbk编码,运行上面代码,就一条简单的命令导致出现错误,说字符串 赋值 没有结束! 呵呵,估计很多人看到这个就会认为是php 出Bug了,

电脑资料

但是,如果我们变成$a=”a”,发现可以正常运行了。是不是觉得很奇葩啦!!

原因分析:我们知道文件存在磁盘都是二级制方式,无论你存什么字符,最终都是以该字符的在所选字符集中字符编码保存。php解析时候,最新分析单元是字节。无论你是多字节,单字节字符。最终都是按照字节来处理的。“”GBK编码是 D55C,php按字节来解释,5C对应字符是“” 字符。后面直接跟个‘”’,相当于被转义了。 因为没有闭合,因此出现错误!。大家看出问题所在了吧,按自己处理的话,会自然把多字节拆成单字节了。这样就会出现很多奇怪问题了。

总结:分析了多字节编码过程,以及产生漏洞原因。其实,我们很多程序语言里面,都会以单个字节来解析的。这样,当你多字节中文中,刚好有字节落在特殊位置,将会出现奇怪的问题。而且,还将给系统带来本身的漏洞,后面我再说说,GBK编码缺陷,导致漏洞的实例吧!欢迎交流!

篇5:字符编码教案

这篇文章主要介绍了go语言实现字符串base64编码的方法,实例分析了Go语言操作字符串的技巧及base64编码的使用技巧,需要的朋友可以参考下

本文实例讲述了go语言实现字符串base64编码的方法,分享给大家供大家参考。具体实现方法如下:

代码如下:

package main

import (

“fmt”

“encoding/base64”

)

func main {

var b bytes.Buffer

w := base64.NewEncoder(base64.URLEncoding, &b)

w.Write(data)

w.Close()

data := b.Bytes()

}

篇6:字符编码教案

[课时]:1节课 [教学目标]:

1、认识电脑键盘的小键盘区的功功能。

2、学会用电脑键盘的小键盘数字键输入数字。

3、学会用电脑键盘的小键盘数字键输入算式。

[教学重点]:学会用电脑键盘的小键盘数字键输入数字。[教学难点]:用正确的指法输入字符 [教学准备]:电脑室 [教学过程]:

一、导入

1、展示教材P19图片,请学生数一数。

2、展示教材P20“开阔视野”图与算式,请学生打开记事本,用主键盘区的数字键试一试输入两个算式: 4594+3447= 4174-926=

3、提问:用主键盘区的数字键进行数字输入,你认为快捷吗?引导学生观察、思考。

倾听学生发言,小结学生发言:在日常生活中,经常要用到数。在电脑中,准确、快捷地输入数字是操作电脑的一项基本功。

4、导入新课:这节课要学会用小键盘数字键输入数字。出示课题:第4课 看图片,输字符。探究活动:手指分工

1、展示教材P21图4—1,引导学生观察小键盘区。

2、展示教材P21图4—2,引导学生认真观察并按照手指分工图,把右手放在小键盘区的键上。

巡视指导,协助需要帮助的学生。

3、请学生尝试在记事本中输入自己家的电话号码。巡视,发现小老师,收集问题。解决问题:

1/2(1)展示小键盘区及上方的指示灯;

(2)引导学生找到NumLock键,再引导学生按NumLock键,观察指示灯的变化。(3)引导学生发现NumLock指示灯,灯亮时,输入数字;灯灭时,小键盘有移动光标的功能。

请小老师指导部分学生把电话号码输完。

4、指导学生指法(老师说,学生做):学生对照指法图,在记事本中输入数字及+、-、*、/符号,老师说一个数字或符号,学生输一个,及时指正学生的指法。

三、练一练:输算式

1、布置练习:P22活动主题第1、2题。

2、巡视指导,协助需要帮助的学生。

3、倾听组长汇报,收集问题并重点讲解,适时点评和评价并做小结。

4、引导没有完成的学生继续完成任务。

四、创新活动

1、布置练习:P23创新活动第1、2、3题。

2、巡视指导,协助需要帮助的学生。适时点评和评价并做小结。

五、比一比

1、题目:P22活动主题中抽取10道算式。

2、比一比谁快,宣布比赛规则。

3、指导学生打开记事本,宣布比赛开始。

4、宣布比赛结束。倾听组长汇报及评价。

5、评价及小结。

六、总结

1、引导学生谈一谈本节课的知识与技能及学习后的收获。

2、引导学生进行自评与互评,评价表参照教材P24活动评价。

篇7:字符编码教案

世界上存在多种文字, 在用计算机处理文字信息时, 为了节省存储空间、提高处理速度, 一些国家和地区为文字制定了相应的字符集, 有的一种文字存在多种字符集。字符集可以以表格形式描述为字符到单字节值或多字节值的映射。ASCII码字符集是所有多字节字符集的一个子集;GB2312字符集是中国大陆制定的, 容纳了6763个简体汉字;Big5字符集是台湾地区制定的, 容纳了13053个繁体字;GBK字符集GB2312的扩展集, 它兼容GB2312, 所以也兼容ASCII, 它能容纳二万多汉字;Unicode字符集设计思想是要它容纳全世界所有文字, 它是国际通用的字符集。

代码页就是指一个字符集, 其中包含数字、标点符号及其他字形。在Windows系列操作系统中, 不同的语言和locale设置会调用不同的代码页。例如英语和大多数欧洲语言使用ANSI代码页1252, 而中国大陆和新加坡使用代码页936 (GBK字符集) , 中国台湾地区使用代码页950 (Big5字符集) 。程序启动时, 自动将多字节代码页设置为操作系统默认的代码页。运行库中大多数多字节字符函数的行为, 与当前多字节代码页设置有关。比如记事本程序 (notepad.exe) 在打开一个ANSI编码的文本时, 会根据操作系统的中的设置来决定使用哪个代码页。这个设置在控制面板—区域和语言选项---高级选项卡----Language for non-Unicode programs设置中, 如果一个文本原本是用代码页936 (简体中文) 编码的, 而操作系统在此处的设置为Chinese (Taiwan) , 用记事本打开时将会显示乱码, 将设置改为Chinese (PRC) 就可正常显示。由于Unicode是国际通用的宽字节字符集, 所以用Unicode编码的文本文件不受此处设置的影响, 都可以正常打开。

2 功能及特点

字符编码转化程序的界面如图1所示。使用这个程序转化文本文件的字符编码时, 只要在“文件名”前的“编辑浏览控件”中选择或者直接输入需要转化的文件路径及其名称, 然后根据需要点击界面中间的命令按钮即可。所生成的新文件名称会在界面最下方的编辑框中显示出来。

3 设计思路

由于字符编码之间没有对应的规律, 如果要把某个文本文件从一种字符编码转为由另一种字符编码来存储, 一般使用查表映射的方式。在Windows系列操作系统中, 使用VC++编程时, 这种字符映射不需要由程序员来编写, 可以使用Windows操作系统提供的两个函数MultiByteToWideChar、 WideCharToMultiByte来实现。

函数MultiByteToWideChar可以把多字节字符串转化为宽字节字符串, 宽字节编码只有Unicode, 这是确定无疑的, 无需特别指出, 而多字节编码种类却有很多, 使用这个函数可以把全部的多字节编码都能分别转化为宽字节编码。它的第一个参数是指与多字节字符相关的代码页, 它的设置可以是非常具体的, 如:936 (表示简体中文) 、950 (表示繁体中文) 、1361 (表示韩国语) 等;也可以相对的、由操作系统或当前程序所处环境决定的, 如CP_ACP、CP_OEMCP、CP_THREAD_ACP等。比如下面函数就可以把简体中文编码的文本转化为Unicode编码:

如果要把繁体中文编码的文本转化为Unicode编码, 只要把上面代码中的MultiByteToWideChar函数的第一个参数改为950就可以。依次类推, 如果要把UTF8编码的文本转化为Unicode编码, 只要把上面代码中的MultiByteToWideChar函数的第一个参数改为CP_UTF8就可以。

函数WideCharToMultiByte的功能是把宽字节字符串转化为多字节字符串, 它的第一个参数也是指与多字节字符相关的代码页, 用法与MultiByteToWideChar基本相同。

4 编程实现

4.1 新建项目

启动Visual Studio 2010, 在“文件”菜单上, 指向“新建”, 然后单击“项目”打开“新建项目”对话框。从Visual C++项目列表中选择“MFC应用程序”, 在“名称”框中键入“changeCharactorSet”, 然后单击“确定”按钮。在“MFC应用程序向导”的“应用程序类型”中, 选择“基于对话框”, 然后不停地点击“下一步”, 最后点击“完成”即可。本项目的字符集要设置为“使用Unicode字符集”。

4.2 在对话框中放置控件

在对话框中放置如图1所示的各个控件, 在表1中, 按照从左到右, 从上到下的顺序对这些控件的类型、ID、标题、相关变量、作用等作了具体的介绍。

4.3 编写用于调用的函数代码

编写下列7段函数代码:

(1) 函数UnicodeToGBK:功能是把Unicode编码的宽字符串转化为GBK编码的多字节字符串:

(2) 函数UnicodeToBig5;功能是把Unicode编码的宽字节符串转化为Big5编码的多字节字符串;只要把函数UnicodeToGBK的函数体中所调用的函数WideCharToMultiByte的第一个参数由936改为950即可。如下所示:

(3) 函数UnicodeToUtf8;功能是把Unicode编码的宽字节符串转化为UTF8编码的多字节字符串。如下所示:

(4) 函数Big5ToUnicode;功能是把Big5编码的多字节字符串转化为Unicode编码的宽字符串。

(5) 函数UTF8ToUnicode;功能是把UTF8编码的多字节字符串转化为Unicode编码的宽字符串。只要把函数Big5ToUnicode的函数体中所调用的函数MultiByteToWideChar的第一个参数由950改为CP_UTF8即可, 如下所示:

(6) 函数GBKToUnicode;功能是把GBK编码的多字节字符串转化为Unicode编码的宽字符串。

(7) 编写一个函数, 用于改变文件名称, 它所生成的新文件名称是由旧文件名称加上当前时间所组成。

4.4 添加各个命令按钮的单击响应消息

(1) 标题为“Unicode转为GBK”命令按钮的单击响应消息:

(2) 标题为“Unicode转为Big5”命令按钮的单击响应消息代码与“Unicode转为GBK”的单击响应消息代码基本相同, 只要把其中所调用的函数UnicodeToGBK改为UnicodeToBig5即可。

(3) 标题为“Unicode转为UTF8”命令按钮的单击响应消息代码与“Unicode转为GBK”的单击响应消息代码基本相同, 只要把其中所调用的函数UnicodeToGBK改为UnicodeToUtf8即可。

(4) 标题为“GBK转为Unicode”命令按钮的单击响应消息:

(5) 标题为“Big5转为Unicode”命令按钮的单击响应消息代码与“GBK转为Unicode”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为Big5ToUnicode即可。

(6) 标题为“UTF8转为Unicode”命令按钮的单击响应消息代码与“GBK转为Unicode”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为UTF8ToUnicode即可。

(7) 多字节字符编码之间相互转化时需要以Unicode编码作为中介。标题为“GBK转为UTF8”命令按钮的单击响应消息:

(8) 标题为“GBK转为Big5”命令按钮的单击响应消息代码与“GBK转为UTF8”的单击响应消息代码基本相同, 只要把其中所调用的函数UnicodeToUtf8改为UnicodeToBig5即可。

(9) 标题为“Big5转为GBK”命令按钮的单击响应消息代码与“GBK转为UTF8”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为Big5ToUnicode, 把UnicodeToUtf8改为UnicodeToGBK即可。

(10) 标题为“Big5转为UTF8”命令按钮的单击响应消息代码与“GBK转为UTF8”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为Big5ToUnicode即可。

(11) 标题为“UTF8转为Big5”命令按钮的单击响应消息代码与“GBK转为UTF8”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为UTF8ToUnicode, 把UnicodeToUtf8改为UnicodeToBig5即可。

(12) 标题为“UTF8转为GBK”命令按钮的单击响应消息代码与“GBK转为UTF8”的单击响应消息代码基本相同, 只要把其中所调用的函数GBKToUnicode改为UTF8ToUnicode, 把UnicodeToUtf8改为UnicodeToGBK即可。

5 结语

介绍了使用VC++编程实现转换文本文件字符编码的方法, 可使文本文件的字符编码在Unicode、Big5、UTF8、GBK等编码之间实现自由转换。所有代码均在VC++2010下通过测试, 实验证明该方法简易实用, 代码的可移植性很强。经过编码转换后的有些文件, 使用Windows操作系统中的“记事本”程序可能无法正确打开, 解决方法是:用鼠标右击该文件, 在弹出菜单的打开方式中选择Microsoft Office Word, Word程序启动后会提示选择“使文档可读的编码”, 选择合适的文本编码, 就能把编码转换后的文件正确打开。

摘要:介绍了使用VC++实现转换文本文件字符编码的方法, 可使文本文件的字符编码在Unicode、Big5、UTF8、GBK等编码之间实现自由转换。

关键词:VC++,字符编码,Unicode,Big5,UTF8,GBK

参考文献

[1]陈小荷.现代汉语自动分析——Visual C++实现[M].北京:北京语言文化大学出版社, 2000.

[2]D.S.Malik.C++编程——数据结构与程序设计方法.晏海华, 等译.北京:电子工业出版社, 2003.

篇8:字符编码教案

报文是通信交换与传输的基本数据单元,承载了数据信息,在实际使用中,为便于观察、交互,许多格式具有特定字符特征,比如广泛使用的NMEA—0183协议。随着信息时代的来临,各种报文的信息呈现海量特性,为共享、存储、分发带来较大压力。比如覆盖整个城市的车辆(公交车、出租车)监控、调度系统,各车辆将自身属性(如位置、状态)等通过特定报文格式经无线信道传输至中心,同时,中心会为各车辆建立历史情况数据库,数量巨大的车辆信息给通信、存储带来不便。同样,在部分窄带信道(如短波、超短波信道)传输报文时,信道速率的提升(功率、天线增益)潜力非常有限,为在有限的带宽中传输尽可能多的信息量,从信源角度进行压缩编码是一种较好的方法。

报文的自身特点要求其压缩编码必须为无损、可逆的,典型的无损编码方法有基于统计模型的BCD编码、Huffman编码和算术编码[1],基于字典模型的LZW编码[2]等。其中,BCD编码可认为是一种等概率Huffman编码模型,而Huffman编码中存在比特数必须取整的问题,其限制了压缩比,LZW编码不适用于猝发、较短报文的处理,上述方法均不适用。算术编码采用以一个单独的浮点数代替一串输入符号的思想,避开了使用一个特定码字代替一个输入符号,被认为是最逼近熵编码[3]极限的一种编码方法,得到了广泛的应用。基于这样一种现状,本文从信源角度出发,提出将算术编码应用于字符型报文的压缩,并对其作出相应优化,经测试,压缩效果良好,大幅提高了报文的传输效率,尤其是窄带信道下的报文传输,效果更为明显。

1算术编码原理

算术编码的基本原理可参考文献[1,4],且根据字符概率统计方法的不同,具体分为静态算术编码和自适应算术编码。静态算术编码的实现包括概率模型建立和扫描编码两个过程,计算量较大,且各符号概率是通过统计信源所有信息而得,由信息熵可知,其压缩效果受限;而自适应算术编码并不需要在编码前统计信源符号的概率分布,而是在编码过程中,随着符号的读入实时地动态更新信源符号的概率分布,从而统计出各符号相对于上下文的概率,压缩效果好于静态模型[5]。

下面以静态算术编码为例,对编码过程具体描述如下

假设某报文字符集合由3个字符{a1,a2,a3}组成,现有一条报文为“a2a3a3a2”, 其字符概率分布如表1所示,P表示字符Code的概率,Range表示字符Code的相应的初始子区间。编码开始之前,初始区间为半开区间[0.0,1.0),如图1中R(begin)所示,依据概率分布,将之分为 [0.0,0.2)、[0.2,0.6)、[0.6,1.0) 互不重叠的3个子区间,分别对应于字符a1、a2、a3,以保证报文中不同字符对应不同的区间;读入第一个符号a2,其对应区间R(a2)映射为 [0.20,0.60),同样依据概率分布将R(a2)再细分为3个子区间。按此过程,逐个读入字符,可发现区间范围逐渐缩小,并在编码结束时,区间缩小为[0.54880,0.57440),即R(a2a3a3a2),且该区间任何一个实数均可以作为编码结果,编解码端采用相同的处理机制即可正确地解码。

2一种新的字符型报文压缩技术

理论上,按照上述方法可以完成算术编码,但是在具体实现过程中还是存在一些问题的,比如概率模型建立、浮点精度等问题。本文提出的字符型报文压缩技术通过引入静态概率表和自适应概率表的建立,实现整数化算术编码,并提出一种直接、有效的编码区间移位方法,不仅解决了这些问题,且压缩比接近或达到熵编码理论的最大值,具体编码步骤见图2。

2.1静态概率表的建立

报文压缩过程中,在初次编码时首先需要对该报文的字符集合进行静态频率表的建立,也即频率表的初始化工作,其主要体现在图2中的预处理步骤。对于静态频率表的建立,现提出其可根据经验值建立,以使报文在编码起始阶段就能够达到较好的压缩效果;也可将其设置为等概率频率表,即Pi=1/N,并且在编码过程中,可根据读入报文动态地进行更新。

2.2自适应概率表的建立

在使用算术编码对读入报文进行编码的过程中,频率表的更新在很大程度上影响着编码效率和压缩比。对于频率表的更新给出了一种优化的自适应更新方法,具体采用两种方式,一是在编码过程中逐字符进行更新,即对本条报文中各个字符进行算术编码后,均更新频率表,具体在图2中表示为“更新频率表方式一”步骤。但是,这种对频率表的更新方式会占用一定的计算量,若计算资源受限则无法适用。对此,提出另外一种方式,即频率表的更新以若干条报文为单位进行,对单条报文逐个字符进行算术编码后,仅记录各个字符出现的次数,在达到设定的若干条报文编码结束后再根据记录情况进行频率表的更新,具体在图2中表示为“更新频率表方式二”步骤。其中,更新频率表方式一充分考虑了字符概率问题,尽可能地增大了报文压缩比,而方式二更是满足了计算资源受限的环境。

2.3整数化算术编码

算术编码在具体实现过程中存在一个致命的缺点,随着信源符号的持续读入,表达编码区间的小数的精度越来越高,其对算术编码在计算机上的实现造成了障碍。文献[6]提出了整数化算术编码的思想,即对于编码区间的表示只取尾数,比如上述举例区间[0.54880,0.57440)可表示为[5488,5744),同时每编码一个符号,均对区间按照一定规则进行更新以及放大,保证下一次编码区间的划分精度。假设算术编码所采用的初始编码区间为[0, Max],Max为区间最大值,一般设置为0xFFFF,编码过程中区间为[Low,High],区间范围为Range,其中Low为区间下沿,初始为0,High为区间上沿,初始为Max,现读入字符为C,其概率为P,累计频率为 CumP,则编码区间的更新公式如式(1)—式(3)所示,而编码区间的放大、移位方法具体参考文献[6,7],且区间放大和移位的信息就是输出码字。该方法使得算术编码可以在有限区间上模拟无限区间的运算,克服了使用计算机时精度受限的问题。

Range=Ηigh-Low+1(1)Ηigh=Low+Range(CumΡ+Ρ)-1(2)Low=Low+RangeCumΡ(3)

但是,显然并不是每编码一个字符都需要进行这样的移位处理,在文献[7]在文献[6]的基础上针对DSP流水线结构提出了一种通过查表判断是否进行移位操作的方法,其不可避免地需要频繁地查表,且适用范围有限。现从编码区间满足解码的基本条件出发(以下称之为可译性),提出一种直接、有效的移位方法,其不仅减少了运算量,而且进一步提高了压缩比。

假设在编码某一字符后自适应频率表中统计的总累计频数为_Total_Freq,当前区间上沿为High,下沿为Low,则可译性可表示为:

Ηigh-Low>=_Τotal_Freq(4)

其实质是指当前编码区间按照总累计频数和各字符的累计频数进行细分区间时,最小区间的大小_Min_Part应满足条件:

_Μin_Ρart>=1(5)

其中,在满足式(4)条件下,当且仅当某一的字符累计频数为1时,式(5)才有可能出现相等的情况。具体编码过程中,若当前编码区间不满足可译性,则进行移位操作(具体参考文献[6]提出的方法),且在区间扩展过程中,若区间满足可译性,即编码下一个字符。同时,_Total_Freq一直处于动态变化中,也即可译性可以根据编码的进展自适应地判断是否需要移位操作。经验证,尤其是在编码初期,减少不必要的移位次数更多,其压缩效果更加明显。

3采用NMEA—0183协议的仿真实验结果

NMEA—0183是美国国家海洋电子协会为海用电子设备制定的标准格式,本节以此报文协议中大地坐标信息格式为例,并假设基于该格式的一条报文Message为:“$GPGLL,0123.4567,S,89012.3456,E,78901.234,A*56”,选取BCD扩展码、Huffman编码和算术编码三种方式进行压缩以及比较。

由于该协议的字符集合由33个字符组成,若使用BCD扩展码压缩,则每个字符需要6个二进制位表示;对于使用Huffman编码压缩,可参考文献[1]中所述方法;同时使用本论文提出的方法压缩。首先仅对一条报文压缩,然后,逐渐增加报文Message的条数至100条,若将压缩比定义为压缩前数据量与压缩后数据量的比值,则对1条、100条报文压缩的数据结果如表2所示,并将Huffman编码和算术编码的压缩过程分别绘制成图3、图4。

通过表2的压缩数据可发现,使用本论文提出的面向字符型报文的算术编码方法对报文进行压缩得到的压缩比相比较其它两种方式有显著的提高。尤其是当字符串的长度越大,字符的概率越明显时,使用算术编码方式的压缩比可以接近甚至达到理论熵极限,而BCD编码和Huffman编码由于未考虑字符间的联合概率等原因,压缩效果相对较差。比如本实例中,当报文条数增至100条时,其压缩比为1.9296,已经非常接近理论压缩比。同时,通过图3、图4的压缩比趋势可以再次验证这一结论。此外,经过对某短波报文传输系统进行连续4个小时的测试,比对结果发现其压缩比平均达到了2.5,效果良好。

4总结

本论文根据报文的字符集合特点,提出了一种适用于字符型报文的无损压缩方法,目前,本方法已在某短波报文传输系统中得到应用, 实现平均约2.5倍的压缩比,压缩后报文长度的缩短还大大降低了传输延时,取得了良好的效果。同时,本文虽面向字符型报文,但其核心实现原理仅对元素集合概率相关,可扩展至任意有限元素集合的报文传输中,在此不再赘述。需要同时指出的是,报文的压缩仅属于报文编码的一部分内容,为能够在工程中应用,还需要统筹考虑报文的同步、校验、纠错、关联、时延等方面,不属于本文探讨的内容,但进行报文压缩后,为采用其它编码方法带来了较大的应用空间。

摘要:文中面向字符型报文,提出了一种全新的无损报文压缩技术。该技术引入算术编码,提出了报文字符集合静态概率表的建立以及自适应概率表更新方法,并提出了一种直接、有效的编码区间移位方法。文中首先采用实例对算术编码原理进行了详细介绍,其次阐述了压缩技术方案原理,并给出了程序设计流程图。最后,以NMEA—0183格式报文为样本进行测试,给出了算术编码以及其它几种无损压缩编码的实验结果,并进行了比较分析。结果表明,文中提出的方法具有良好的压缩效果。

关键词:无损压缩,字符型报文,算术编码

参考文献

[1]Sayood K.数据压缩导论.北京:人民邮电出版社,2009

[2]王平.LZW无损压缩算法的实现与研究.计算机工程,2002;28(7):98—150

[3] Shannon C E.A mathematical theory of communication.Bell SystemTechnical Journal,1948;27:379—423,623—656

[4]李彬,倪桂强,罗健欣.多阶自适应算术编码研究.微型机与应用,2010;29(12):71—74

[5]杨文涛,刘卫忠,郑立新,等.多阶上下文自适应二进制算术编码实现.华中科技大学学报(自然科学版),2007;35(3):42—45

[6] Witten I H,Neal R M,Cleary J G.Arithmetic coding for data com-pression.Communications of the ACM,1987;30(6):520—541

上一篇:温差发电实验报告下一篇:少了的高中作文750字