乱码算法大全

来源:互联网 发布:淘宝商家怎么做直播 编辑:程序博客网 时间:2024/05/16 19:11

武汉白云黄鹤站∶精华区
发信人: mogao (莫高), 信区: Algorithm
标  题: 乱码算法大全——序
发信站: 武汉白云黄鹤站 (Wed Apr 12 14:54:04 2000), 站内信件
 
                    乱码算法大全
                        序
    相信上过网的朋友们都遇见过“乱码”,
也就是在浏览网页或看Email时出现的不能辨认的字符。
以前也有许多的文章介绍过“乱码”,不过他们的文章
只是讲怎样辨别和怎样用工具解码,并没有详细介绍各
种编码的算法的实现,本文将对互联网上最常用的几种
编码的编码和解码算法作以详细的阐述。希望对想了解
“乱码”算法或想在自己程序中实现这些功能朋友们有
一些参考价值。本文的源程序用C语言写成,形式为函
数,可直接使用。
 
 
--

发信人: mogao (莫高), 信区: Algorithm
标  题: 乱码算法大全(一)
发信站: 武汉白云黄鹤站 (Wed Apr 12 14:57:34 2000), 站内信件
 
一. 常用编码
1. Uuencode
    Uuencode 是将二进制文件以文本文件方式进行编码表示、
以利于基于文本传输环境中进行二进制文件的传输/交换的编
码方法之一, 在邮件系统/二进制新闻组中使用频率比较高,
经常用于 Attach 二进制文件。
    这种编码的特征是:每一行开头用“M”标志。下面是我
做的一个测试用的文件mogao.txt,编码为Uuencode:
begin 644 mogao.txt
M"0D)("`@(*&VPM+"Z/OCMZBT//BKH;<-"@G7]]7?.FUO9V%OHZRPU]3&N/:Z
MU]6^HZAT96QN970Z+R/R,#(N,3$R+C(P+C$S,CHR,Z.IL/G4L:&C#0H)("`@
M("`@Q*JXW/CMO/ZYI-?WRM*CNFAT='`Z+R]M;V=A;RYB96YT:75N+FYE=`T*
M"0D)16UA:6QT;SIM;V=A;T`S-S$N;F5T#0H)("`@*BHJ*BHJ*BHJ*BHJ*BHJ
M*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ("`@("`@("`@("`@("`@
M#0H)("`@*B"S_<'+O,?2Y,JRP[2VO+*[M/C7WZ.LL_W!R]?CO*/*LL.TMKRR
MN/'TS/(J#0H)("`@*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ*BHJ
,*BHJ*BHJ*BHJ*BHJ
`
end
    你可以把它单独存成一个文件:mogao.uue,然后用Winzip
打开,解压即得mogao.txt。
    Uuencode的算法很简单,编码时它将3个字符顺序放入一个
 24 位的缓冲区,缺字符的地方补零,然后将缓冲区截断成为
4 个部分,高位在先,每个部分 6 位,用下面的64个字符重新
表示:
"`!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_"
在文件的开头有“begin xxx 被编码的文件名”,在文件的结尾
有“end”,用来标志Uue文件的开始和结束。编码时,每次读取
源文件的45个字符,不足45个的用“NULL”补足为3的整数倍(
如:23补为24),然后输入目标文件一个ASCII为:“32+实际
读取的字符数”的字符作为每一行的开始。读取的字符编码后
输入目标文件,再输入一个“换行符”。如果源文件被编码完
了,那么输入“`(ASCII为96)”和一个“换行符”表示编码
结束。
    解码时它将4个字符分别转换为4个6位字符后,截取有用的
后六位放入一个 24 位的缓冲区,即得3个二进制代码。
    下面我给出Uuencode编码和解码的C语言描述:
/*Uuencode编码*/
void Uue(unsigned char chasc[3],unsigned char chuue[4])
/*
chasc:未编码的二进制代码
chuue:编码过的Uue代码
*/
{int i,k=2;
 unsigned char t=NULL;
 for(i=0;i<3;i++)
 {*(chuue+i)=*(chasc+i)>>k;
  *(chuue+i)|=t;
  if(*(chuue+i)==NULL) *(chuue+i)+=96;
  else *(chuue+i)+=32;
  t=*(chasc+i)<<(8-k);
  t>>=2;
  k+=2;
 }
 *(chuue+3)=*(chasc+2)&63;
 if(*(chuue+3)==NULL) *(chuue+3)+=96;
 else *(chuue+3)+=32;
}
/*Uuencode解码*/
void unUue(unsigned char chuue[4],unsigned char chasc[3])
/*
chuue:未解码的Uue代码
chasc:解码过的二进制代码
*/
{int i,k=2;
 unsigned char t=NULL;
 if(*chuue==96) *chuue=NULL;
 else *chuue-=32;
 for(i=0;i<3;i++)
 {*(chasc+i)=*(chuue+i)<<k;
  k+=2;
  if(*(chuue+i+1)==96) *(chuue+i+1)=NULL;
  else *(chuue+i+1)-=32;
  t=*(chuue+i+1)>>8-k;
  *(chasc+i)|=t;
 }
}
2. Xxencode
    提到Uuencode不可能不提Xxencode, Xxencode的编码算法
和 Uuencode基本相同,但是使用的是不同的字符集。XxEncode
编码使用的字符是:
“+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”
与 Uuencode 相比,它的特殊字符更少。很多支持 Uuencode
编解码的工具都同时支持 Xxencode。
    这种编码的特征是:每一行开头用“h”标志。下面是
Xxencode的一个例子:
begin 644 mogao.txt
h0EY760+U684qkh90uwjXhuWowwWfcPQB0UbLxxLTCapjNq3jcumkpxH4iwOu
hpxKycuVoNKliNLEu9mwmA16iAH2m9X6k9X2nAXcmAuCdgwbIgO4X1Ec760+U
h60+Ul8esrwXhjDutdBTrmh8XiaVoR5+u9mxhPqRVPmtWNKtoOLJi9atZR+o8
h0EY7FKpVOKloPndhPqRVPo+nBn2iPaJo1Ec760+U8Wce8Wce8Wce8Wce8Wce
h8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce60+U60+U60+U60+U60+U
h1Ec760+U8W0nzQ59jATGtAemkvGqj98vhDXLruCggzr-mxTXj8D8ggCohfmm
hiw5onw6e1Ec760+U8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce8Wce
A8Wce8Wce8Wce8Wce
+
end
    你可以把它单独存成一个文件:mogao.xxe,然后用Winzip
打开,解压即得mogao.txt。
    Xxencode的编码算法和Uuencode基本相同,实现起来则更
为简单,在此就不详述了。
    下面给出Xxencode编码和解码的C语言描述:
/*Xxencode编码*/
 void Xxe(unsigned char chasc[3],unsigned char chxxe[4])
/*
chasc:未编码的二进制代码
chxxe:编码过的Xxe代码
*/
{int i;
 static char set[]=
  "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 chxxe[0]=chasc[0]>>2;
 chxxe[1]=(chasc[0]<<4)&48|(chasc[1]>>4)&15;
 chxxe[2]=(chasc[1]<<2)&60|(chasc[2]>>6)&3;
 chxxe[3]=chasc[2]&63;
 for(i=0;i<4;i++) chxxe[i]=set[chxxe[i]];                       /*查表*/
}
/*需注意的是,Xxencode文件正文部分中每一行的第一个字母是
:从源文件中实际读取的字符数的ASCII值取后六位后用set[]查
表得到的。*/
/*Xxencode解码*/
unsigned char set(unsigned char ch)                             /*查表函数*/
{if(ch==43) ch=0;
 else if(ch==45) ch=1;
 else if(ch>=48&&ch<=57) ch-=46;
 else if(ch>=65&&ch<=90) ch-=53;
 else if(ch>=97&&ch<=122) ch-=59;
 return ch;
}
void unXxe(unsigned char chxxe[4],unsigned char chasc[3])
/*
chxxe:未解码的Xxe代码
chasc:解码过的二进制代码
*/
{int k=2 ,i;
 unsigned char t;
 t=NULL;
 *chxxe=set(*chxxe);
 for(i=0;i<3;i++)
 {*(chxxe+i+1)=set(*(chxxe+i+1));
  (chhex+i)=*(chxxe+i)<<k;
  k+=2;
  t=*(chxxe+i+1)>>8-k;
  *(chhex+i)|=t;
 }
}
 
 

发信人: mogao (莫高), 信区: Algorithm
标  题: 乱码算法大全(二)
发信站: 武汉白云黄鹤站 (Wed Apr 12 15:00:20 2000), 站内信件
 
3. Base64
    Base64和下面将要介绍的Quoted-Printable都属于MIME
(多部分( multi-part)、多媒体电子邮件和 WWW 超文本的
一种编码标准,用于传送诸如图形、声音和传真等非文本数
据)。MIME定义在RFC1341中。
    Base64是现今在互联网上应用最多的一种编码,几乎所
有的电子邮件软件头把它作为默认的二进制编码,它已经成
了现今电子邮件编码的代名词。
    下面是Base64的一个例子,从例子中,您也可以看到
Base64与电子邮件的的紧密联系:
Content-Type: text/plain;charset="cn-gb"
Content-Transfer-Encoding: BASE64
CQkJICAgIKG2wtLC68vjt6i088irobcNCgnX99XfOm1vZ2Fvo6yw19TGu8a619W+o6h0ZWxuZXQ6
 
Ly8yMDIuMTEyLjIwLjEzMjoyM6Ops8nUsaGjDQoJICAgICAgxKq438jtvP65pNf3ytKjumh0dHA6
 
Ly9tb2dhby5iZW50aXVuLm5ldA0KCQkJRW1haWx0bzptb2dhb0AzNzEubmV0DQoJICAgKioqKioq
 
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICAgICAgICAgICAgICAgDQoJ
 
ICAgKiCz/cHLvMfS5Mqyw7S2vLK7tPjX36Oss/3By9fjvKPKssO0tryyu8H0z8IqDQoJICAgKioq
 
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
    你可以把它单独存成一个文件,可以取名为:mogao.eml,
双击可以用OutLook打开(前两行为邮件的原始信息,从第四行
开始为编码内容)。
    Base64的算法同Uuencode的算法很接近,也很简单:它将
字符流顺序放入一个 24 位的缓冲区,缺字符的地方补零。然
后将缓冲区截断成为 4 个部分,高位在先,每个部分 6 位,
用下面的64个字符重新表示:“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
wxyz0123456789+/”。
如果输入只有一个或两个字节,那么输出将用等号“=”补足。
这可以隔断附加的信息造成编码的混乱。它每行一般为76个字符。
    下面我给出Base64的编码和解码的C语言描述:
/*Base64编码*/
void Base64(unsigned char chasc[3],unsigned char chuue[4])
/*
  chasc:未编码的二进制代码
  chuue:编码过的Base64代码
*/
{
 int i,k=2;
 unsinged char t=NULL;
 for(i=0;i<3;i++)
 {
  *(chuue+i)=*(chasc+i)>>k;
  *(chuue+i)|=t;
  t=*(chasc+i)<<(8-k);
  t>>=2;
  k+=2;
 }
 *(chuue+3)=*(chasc+2)&63;
 for(i=0;i<4;i++)
    if((*(chuue+i)>=0)&&(*(chuue+i)<=25)) *(chuue+i)+=65;
    else if((*(chuue+i)>=26)&&(*(chuue+i)<=51)) *(chuue+i)+=71;
    else if((*(chuue+i)>=52)&&(*(chuue+i)<=61)) *(chuue+i)-=4;
    else if(*(chuue+i)==62) *(chuue+i)=43;
    else if(*(chuue+i)==63) *(chuue+i)=47;
}
/*Base64解码*/
void unBase64(unsigned char chuue[4],unsigned char chasc[3])
/*
chuue:未解码的Base64代码
chasc:解码过的二进制代码
*/
{int i,k=2;
 unsigned char t=NULL;
 for(i=0;i<4;i++)
     if((*(chuue+i)>=65)&&(*(chuue+i)<=90)) *(chuue+i)-=65;
     else if((*(chuue+i)>=97)&&(*(chuue+i)<=122)) *(chuue+i)-=71;
     else if((*(chuue+i)>=48)&&(*(chuue+i)<=57)) *(chuue+i)+=4;
     else if(*(chuue+i)==43) *(chuue+i)=62;
     else if(*(chuue+i)==47) *(chuue+i)=63;
     else if(*(chuue+i)==61) *(chuue+i)=0;
 for(i=0;i<3;i++)
 {*(chhex+i)=*(chuue+i)<<k;
  k+=2;
  t=*(chuue+i+1)>>8-k;
  *(chhex+i)|=t;
 }
}
4. Quoted-Printable
    Quoted-Printable简称QP, 一般用在Email系统中。它
通常用于少量文本方式的8位字符的编码,例如Foxmail就用
它做对主题和信体的编码。这种编码的应该是很好辨认的:
它有大量的“=”。下面是它的一个例子:
Mime-Version: 1.0
Content-Transfer-Encoding: quoted-printable
                            =A1=B6=C2=D2=C2=EB=CB=E3=B7=A8=B4=F3=C8=AB=A1=B7
        =D7=F7=D5=DF:mogao=A3=AC=B0=D7=D4=C6=BB=C6=BA=D7=D5=BE=A3=A8telnet://202.11
2.20.132:23=A3=A9=B3=C9=D4=B1=A1=A3
              =C4=AA=B8=DF=C8=ED=BC=FE=B9=A4=D7=F7=CA=D2=A3=BAhttp://mogao.bentiun.
net
                        Emailto:mogao@371.net
           *********************************************
           * =B3=FD=C1=CB=BC=C7=D2=E4=CA=B2=C3=B4=B6=BC=B2=BB=B4=F8=D7=DF=A3=AC=B3=
FD=C1=CB=D7=E3=BC=A3=CA=B2=C3=B4=B6=BC=B2=BB=C1=F4=CF=C2*
           *********************************************
    你可以把它单独存成一个文件,取名为:mogao.eml,
双击可以用OutLook打开(前两行为邮件的原始信息,从第
四行开始为编码内容)。
    QP的算法可以说是最简单的也可以说是编码效率最低的
(它的编码率是1:3),它是专门为了处理8位字符制定的。
它的算法是:读一个字符,如果ASCII码大于127,即字符的
第8位是1的话,进行编码,否则忽略(有时也对7位字符编码)。
编码很简单,看下面的C语言描述即可:
/*QP编码*/
void qp(unsigned char sour,unsigned char first,unsigned char second)
/*
  sour:要编码的字符
  first:编码后的第一个字符
   second:编码后的第二个字符
  first和second为返回值
*/
{
 if(sour>127)
 {first=sour>>4;
  second=sour&15;
  if(first>9) first+=55;
  else first+=48;
  if(second>9) second+=55;
  else second+=48;
  printf("%c%c%c",'=',first,second);
 }
}
/*QP解码*/
void uqp(unsigned char sour,unsigned char first,unsigned char second)
/*
  sour:解码后的字符
  first:QP码的第一个字符
   second:QP码的第二个字符
  sour为返回值
*/
{
 if(first>=65) first-=55;
 else first-=48;
 if(second>=65) second-=55;
 else second-=48;
 sour=NULL;
 sour=first<<4;
 sour|=second;
}
    现在大家知道为什么QP的编码率那么低了吧!关于QP的
详细说明和准确定义可以参阅RFC2045。
 
 
--

发信人: mogao (莫高), 信区: Algorithm
标  题: 乱码算法大全(三)
发信站: 武汉白云黄鹤站 (Wed Apr 12 15:03:49 2000), 站内信件
 
二.汉字编码
1. GB码和Big5码
    GB码是中国大陆、新加坡等国家和地区使用的一种汉字
编码方法。Big5码是中国台湾省用的一种汉字编码方法。它
们的编码方法是完全不同的两种方法,它们之间的转换只能
通过“查表法”来进行。所以说转换的方法很简单,困难的
是“表”的生成。很多文章对此都做过介绍,我在此就不详
述了。在我的主页上有我写的“汉字转码通V1.0”的源程序,
其中有这两个“表”,可以直接使用。
2. HZ码
    HZ码是为了使只能传送7bit信息的邮件服务器或网关能
传送8bit信息而定义的编码,也是中文常用编码的一种。它
和上面介绍的Quoted-Printable码都只能对文本进行编码,
即编码时忽略控制字符。
    这种编码的也是很好辨认的:有许多“~{”和“~}”,
而且总是成对出现。下面是HZ码的一个例子:
                            ~{!6BRBkKc7(4sH+!7~}
        ~{WwU_~}:mogao~{#,0WTF;F:WU>#(~}telnet://202.112.20.132:23~{#)3IT1!#~}
              ~{D*8_Hm<~9$WwJR#:~}http://mogao.bentiun.net
                        Emailto:mogao@371.net
           *********************************************
           * ~{3}AK<GRdJ2C46<2;4xW_#,3}AKWc<#J2C46<2;AtOB~}*
           *********************************************
    您可以打开“南极星”看这段文字。
    它的算法更简单:读一个字符,如果是8位字符,就把它
的最高位清零。把连续的8位字符清零后的输出用“~{”和“~}”
括起来。解码时:把是用“~{”和“~}”括起来的部分每个字符
的第8位置“1”即可。
    上面介绍的三种编码之间的转换是经常遇见的,我写的“汉
字转码通V1.0”可以方便的在这三种之间转换,我把它的源程序
公开,方便广大网友的学习。
三.其他常用编码
1.  Unicode
    Unicode应用中最典型的例子是:IE4以上版本对HTML的编码。
它可以说是未来Windows下唯一的字符集。但它还很不完善,而
且Win95和Win98对它的支持还很有限,甚至它还没有一套完整的
标准。不过,微软最新推出的Office2000和马上就要推出的Windows2000
将全面支持Unicode。Unicode取代其他编码将会是必然的趋势。
不过,在近一两年Unicode并不会占主导地位,就是在占主导地位后,
因为操作系统的差异,其他编码也不会立即消亡。它的中文资料可以
在Office2000和Windows2000所带的文档中找到,它的官方网站是:
http://www.unicode.org/。
2. Binhex
    BinHex 编码是 Macintosh 计算机(也就是俗称的“苹果电
脑”)上用可打印字符表示/传输二进制文件的一种编码方法。它
的主要用途是在电子邮件程序中Attach二进制文件。大部分的电
子邮件程序不支持这种格式(Eudora支持),但用WINZIP可以进
行解码。它的资料请查阅Macintosh计算机带的相关文档。
三.总结
    由于篇幅所限,除了本文介绍的这几种常用编码外,还是有
很多种编码的。如各种加密算法产生的“乱码”(我将在另外一
篇文章中详细介绍)。本文中提到的所有文档和源程序在我的主
页中均可下载,我的主页地址是:http://mogao.bentium.net。
如果您对本文有什么意见请来信商榷,我的E-mail地址是:
mogao@371.net。
注:我在本文中使用的例子“mogao.txt”的内容是:
                            《乱码算法大全》
        作者:mogao,白云黄鹤站(telnet://202.112.20.132:23)成员。
              莫高软件工作室:http://mogao.bentiun.net
                        Emailto:mogao@371.net
           *********************************************
           * 除了记忆什么都不带走,除了足迹什么都不留下*
           *********************************************
 
 
--
                            莫畏高险  勇攀高峰
                           除了足迹什么都不留下
                           除了记忆什么都不带走
莫高软件工作室:
               http://mogaosoft.126.com
               http://home.gbsource.net/mogao
 
※ 来源:.武汉白云黄鹤站 bbs.whnet.edu.cn.[FROM: 202.196.73.130]

华中地区网络中心
武汉白云黄鹤站∶精华区
发信人: mogao (莫高), 信区: Algorithm
标  题: 乱码算法大全——后记
发信站: 武汉白云黄鹤站 (Wed Apr 12 15:11:54 2000), 站内信件
 
这篇文章是我在去年写的,本来早就想放上来的,不好意思,
一直拖到现在。
写得很粗糙,如果能给大家有一点帮助的话,我就很满意了。
如有错误或是有事咨询的话,请大家给我发email:mogao@371.net
谢谢。
 
--
                            莫畏高险  勇攀高峰
                           除了足迹什么都不留下
                           除了记忆什么都不带走
莫高软件工作室:
               http://mogaosoft.126.com
               http://home.gbsource.net/mogao
 
※ 来源:.武汉白云黄鹤站 bbs.whnet.edu.cn.[FROM: 202.196.73.130]

华中地区网络中心