字符编码之间的相互转换文档格式.docx
《字符编码之间的相互转换文档格式.docx》由会员分享,可在线阅读,更多相关《字符编码之间的相互转换文档格式.docx(10页珍藏版)》请在冰点文库上搜索。
所谓文本文件就是我们按一定编码方式将二进制数据表示为对应的文本如00这样的文件。
我用一个支持zixia编码和aka字符集的记事本打开,它就按照编码方案显示为“香蕉是个大笨蛋”如果我把这些字符按照GBK另存一个文件,那么则肯定不是这个,而是1010101101001111001110110100001010
二,字符集
1,常用字符集分类ASCII及其扩展字符集作用:
表语英语及西欧语言。
位数:
ASCII是用7位表示的,能表示128个字符;
其扩展使用8位表示,表示256个字符。
范围:
ASCII从00到7F,扩展从00到FF。
ISO-8859-1字符集作用:
扩展ASCII,表示西欧、希腊语等。
8位,范围:
从00到FF,兼容ASCII字符集。
GB2312字符集作用:
国家简体中文字符集,兼容ASCII。
使用2个字节表示,能表示7445个符号,包括6763个汉字,几乎覆盖所有高频率汉字。
高字节从A1到F7,低字节从A1到FE。
将高字节和低字节分别加上0XA0即可得到编码。
BIG5字符集作用:
统一繁体字编码。
使用2个字节表示,表示13053个汉字。
高字节从A1到F9,低字节从40到7E,A1到FE。
GBK字符集作用:
它是GB2312的扩展,加入对繁体字的支持,兼容GB2312。
使用2个字节表示,
可表示21886个字符。
高字节从81到FE,低字节从40到FE。
GB18030字符集作用:
它解决了中文、日文、朝鲜语等的编码,兼容GBK。
它采用变字节表示(1ASCII,2,4字节)。
可表示27484个文字。
1字节从00到7F;
2字节高字节从81到FE,低字节从40到7E和80到FE;
4字节第一三字节从81到FE,第二四字节从30到39。
UCS字符集作用:
国际标准ISO10646定义了通用字符集(UniversalCharacterSet)。
它是与UNICODE同类的组织,UCS-2和UNICODE兼容。
它有UCS-2和UCS-4两种格式,分别是2字节和4字节。
目前,UCS-4只是在UCS-2前面加了0×
0000。
UNICODE字符集作用:
为世界650种语言进行统一编码,兼容ISO-8859-1。
UNICODE字符集有多个编码方式,分别是UTF-8,UTF-16和UTF-32。
2,按所表示的文字分类语言字符集正式名称英语、西欧语ASCII,ISO-8859-1MBCS多字节简体中文GB2312MBCS多字节繁体中文BIG5MBCS多字节简繁中文GBKMBCS多字节中文、日文及朝鲜语GB18030MBCS多字节各国语言UNICODE,UCSDBCS宽字节三
编码UTF-8:
采用变长字节(1ASCII,2希腊字母,3汉字,4平面符号)表示,网络传输,即使错了一个字节,不影响其他字节,而双字节只要一个错了,其他也错了,具体如下:
如果只有一个字节则其最高二进制位为0;
如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。
UTF-8最多可用到6个字节。
UTF-16:
采用2字节,Unicode中不同部分的字符都同样基于现有的标准。
这是为了便于转换。
从0×
0000到0×
007F是ASCII字符,从0×
0080到0×
00FF是ISO-8859-1对ASCII的扩展。
希腊字母表使用从0×
0370到0×
03FF的代码,斯拉夫语使用从0×
0400到0×
04FF的代码,美国使用从0×
0530到0×
058F的代码,希伯来语使用从0×
0590到0×
05FF的代码。
中国、日本和韩国的象形文字(总称为CJK)占用了从0×
3000到0×
9FFF的代码;
由于0×
00在c语言及操作系统文件名等中有特殊意义,故很多情况下需要UTF-8编码保存文本,去掉这个0×
00。
举例如下:
0×
0080=0000000010000000UTF-8:
0xC280=1100001010000000UTF-32:
采用4字节。
优缺点UTF-8、UTF-16和UTF-32都可以表示有效编码空间(U+000000-U+10FFFF)内的所有Unicode字符。
使用UTF-8编码时ASCII字符只占1个字节,存储效率比较高,适用于拉丁字符较多的场合以节省空间。
对于大多数非拉丁字符(如中文和日文)来说,UTF-16所需存储空间最小,每个字符只占2个字节。
WindowsNT内核是Unicode(UTF-16),采用UTF-16编码在调用系统API时无需转换,处理速度也比较快。
采用UTF-16和UTF-32会有BigEndian和LittleEndian之分,而UTF-8则没有字节顺序问题,所以UTF-8适合传输和通信。
UTF-32采用4字节编码,一方面处理速度比较快,但另一方面也浪费了大量空间,影响传输速度,因而很少使用。
四,如何判断字符集1,字节序首先说一下字节序对编码的影响,字节序分为BigEndian字节序和LittleEndian字节序。
不同的处理器可能不一样。
所以,传输时需要告诉处理器当时的编码字节序。
对于前者而言,高位字节存在低地址,低字节存于高地址;
后者相反。
例如,0X03AB,BigEndian字节序0000:
030001:
ABLittleEndian字节序是0000:
AB0001:
032,编码识别UNICODE,根据前几个字节可以判断UNICODE字符集的各种编码,叫做ByteOrderMask方法BOM:
UTF-8:
EFBBBF(符合UTF-8格式,请看上面。
但没有含义在UCS即UNICODE中)UTF-16BigEndian:
FEFF(没有含义在UCS-2中)UTF-16LittleEndian:
FFFE(没有含义在UCS-2中)UTF-32BigEndian:
0000FEFF(没有含义在UCS-4中)UTF-32LittleEndian:
FFFE0000(没有含义在UCS-4中)GB2312:
高字节和低字节的第1位都是1。
BIG5,GBK&
GB18030:
高字节的第1位为1。
操作系统有默认的编码,常为GBK,可以下载别的并升级。
通过判断高字节的第1位从而知道是ASCII或者汉字编码。
#include<
stdio.h>
#include<
windows.h>
//GBK编码转换到UTF8编码
intGBKToUTF8(unsignedchar*lpGBKStr,unsignedchar*lpUTF8Str,intnUTF8StrLen){
wchar_t*lpUnicodeStr=NULL;
intnRetLen=0;
if(!
lpGBKStr)//如果GBK字符串为NULL则出错退出return0;
nRetLen=:
:
MultiByteToWideChar(CP_ACP,0,(char*)lpGBKStr,-1,NULL,NULL);
//获取转换到Unicode编码后所需要的字符空间长度
lpUnicodeStr=newWCHAR[nRetLen+1];
//为Unicode字符串空间
MultiByteToWideChar(CP_ACP,0,(char*)lpGBKStr,-1,lpUnicodeStr,nRetLen);
//转换到Unicode编码
nRetLen)//转换失败则出错退出return0;
WideCharToMultiByte(CP_UTF8,0,lpUnicodeStr,-1,NULL,0,NULL,NULL);
//获取转换到UTF8编码后所需要的字符空间长度
lpUTF8Str)//输出缓冲区为空则返回转换后需要的空间大小{
if(lpUnicodeStr)delete[]lpUnicodeStr;
returnnRetLen;
}
if(nUTF8StrLen<
nRetLen)//如果输出缓冲区长度不够则退出{
if(lpUnicodeStr)
delete[]lpUnicodeStr;
return0;
WideCharToMultiByte(CP_UTF8,0,lpUnicodeStr,-1,(char*)lpUTF8Str,nUTF8StrLen,NULL,NULL);
//转换到UTF8编码
returnnRetLen;
//使用这两个函数的例子intmain(){
charcGBKStr[]="
我是中国人!
"
;
char*lpGBKStr=NULL;
char*lpUTF8Str=NULL;
FILE*fp=NULL;
nRetLen=GBKToUTF8((unsignedchar*)cGBKStr,NULL,NULL);
printf("
转换后的字符串需要的空间长度为:
%d"
nRetLen);
lpUTF8Str=newchar[nRetLen+1];
nRetLen=GBKToUTF8((unsignedchar*)cGBKStr,(unsignedchar*)lpUTF8Str,nRetLen);
if(nRetLen){
printf("
GBKToUTF8转换成功!
);
}else{
GBKToUTF8转换失败!
gotoRet0;
fp=fopen("
C:
\\GBKtoUTF8.txt"
"
wb"
//保存到文本文件fwrite(lpUTF8Str,nRetLen,1,fp);
fclose(fp);
getchar();
//先去打开那个文本文件看看,单击记事本的“文件”-“另存为”菜单,在对话框中看到编码框变为了“UTF-8”说明转换成功了
Ret0:
{
if(lpGBKStr)
delete[]lpGBKStr;
if(lpUTF8Str)
delete[]lpUTF8Str;
return0;
1classCChineseCode
2
3{4
5public:
6
7staticvoidUTF_8ToUnicode(wchar_t*pOut,char*pText);
//把UTF-8转换成Unicode89staticvoidUnicodeToUTF_8(char*pOut,wchar_t*pText);
//Unicode转换成UTF-81011staticvoidUnicodeToGB2312(char*pOut,wchar_tuData);
//把Unicode转换成GB231212
13staticvoidGb2312ToUnicode(wchar_t*pOut,char*gbBuffer);
//GB2312转换成Unicode14
15staticvoidGB2312ToUTF_8(string&
pOut,char*pText,intpLen);
//GB2312转为UTF-816
17staticvoidUTF_8ToGB2312(string&
pOut,char*pText,intpLen);
//UTF-8转为GB23121819};
20
21类实现22
23voidCChineseCode:
UTF_8ToUnicode(wchar_t*pOut,char*pText)2425{26
27char*uchar=(char*)pOut;
28
29uchar[1]=((pText[0]&
0x0F)<
<
4)+((pText[1]>
>
2)&
0x0F);
30
31uchar[0]=((pText[1]&
0x03)<
6)+(pText[2]&
0x3F);
32
33return;
3435}36
37voidCChineseCode:
UnicodeToUTF_8(char*pOut,wchar_t*pText)3839{40
41//注意WCHAR高低字的顺序,低字节在前,高字节在后42
43char*pchar=(char*)pText;
44
45pOut[0]=(0xE0|((pchar[1]&
0xF0)>
4));
46
47pOut[1]=(0x80|((pchar[1]&
2))+((pchar[0]&
0xC0)>
6);
48
49pOut[2]=(0x80|(pchar[0]&
0x3F));
50
51return;
5253}54
55voidCChineseCode:
UnicodeToGB2312(char*pOut,wchar_tuData)5657{58
59WideCharToMultiByte(CP_ACP,NULL,&
uData,1,pOut,sizeof(wchar_t),NULL,NULL);
60
61return;
62
63}64
65voidCChineseCode:
Gb2312ToUnicode(wchar_t*pOut,char*gbBuffer)66
67{68
69:
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
70
71return;
7273}74
75voidCChineseCode:
GB2312ToUTF_8(string&
pOut,char*pText,intpLen)7677{78
79charbuf[4];
80
81intnLength=pLen*3;
82
83char*rst=newchar[nLength];
84
85memset(buf,0,4);
86
87memset(rst,0,nLength);
88
89inti=0;
90
91intj=0;
92
93while(i<
pLen)94
95{96
97//如果是英文直接复制就可以98
99if(*(pText+i)>
=0)100
101{102
103rst[j++]=pText[i++];
104
105}106
107else108
109{
110
111wchar_tpbuffer;
112
113Gb2312ToUnicode(&
pbuffer,pText+i);
114
115UnicodeToUTF_8(buf,&
pbuffer);
116
117unsignedshortinttmp=0;
118
119tmp=rst[j]=buf[0];
120
121tmp=rst[j+1]=buf[1];
122
123tmp=rst[j+2]=buf[2];
124
125j+=3;
126
127i+=2;
128
129}130
131}132
133rst[j]='
'
134
135//返回结果136
137pOut=rst;
138
139delete[]rst;
140
141return;
142143}144
145voidCChineseCode:
UTF_8ToGB2312(string&
pOut,char*pText,intpLen)146147{148149char*newBuf=newchar[pLen];
150
151charCtemp[4];
152
153memset(Ctemp,0,4);
154
155inti=0;
156
157intj=0;
158
159while(i<
pLen)160
161{162
163if(pText>
0)164
165{166
167newBuf[j++]=pText[i++];
168
169}170
171else172
173{174
175WCHARWtemp;
176
177UTF_8ToUnicode(&
Wtemp,pText+i);
178
179UnicodeToGB2312(Ctemp,Wtemp);
180
181newBuf[j]=Ctemp[0];
182
183newBuf[j+1]=Ctemp[1];
184
185i+=3;
186
187j+=2;
188
189}190
191}192
193newBuf[j]='
194
195pOut=newBuf;
196
197delete[]newBuf;
198
199return;
200
201}
1、将GBK转换成UTF8
stringGBKToUTF8(conststd:
string&
strGBK){stringstrOutUTF8="
WCHAR*str1;
intn=MultiByteToWideChar(CP_ACP,0,strGBK.c_str(),-1,NULL,0);
str1=newWCHAR[n];
MultiByteToWideChar(CP_ACP,0,strGBK.c_str(),-1,str1,n);
n=WideCharToMultiByte(CP_UTF8,0,str1,-1,NULL,0,NULL,NULL);
char*str2=newchar[n];
WideCharToMultiByte(CP_UTF8,0,str1,-1,str2,n,NULL,NULL);
strOutUTF8=str2;
delete[]str1;
str1=NULL;
delete[]str2;
str2=NULL;
returnstrOutUTF8;
WideCharToMultiByte把UNICODE转换成ASCII码。
2、将UTF8转换成GBK
stringUTF8ToGBK(conststd:
strUTF8){
intlen=MultiByteToWideChar(CP_UTF8,0,strUTF8.c_str(),-1,NULL,0);
unsignedshort*wszGBK=newunsignedshort[len+1];
memset(wszGBK,0,len*2+2);
MultiByteToWideChar(CP_UTF8,0,(LPCTSTR)strUTF8.c_str(),-1,wszGBK,len);
len=WideCharToMultiByte(CP_ACP,0,wszGBK,-1,NULL,0,NULL,NULL);
char*szGBK=newchar[len+1];
memset(szGBK,0,len+1);
WideCharToMultiByte(CP_ACP,0,wszGBK,-1,szGBK,len,NULL,NULL);
//strUTF8=szGBK;
std:
stringstrTemp(szGBK);