不同字符编码格式之间的转换

一、概述

为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 ‘中‘ 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。

二、编码格式分类

1、ansi编码

不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码 代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。

对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。这一点是ASNI编码与Unicode编码之间最大也最明显的区别。比如“A君是第131号”,在ANSI编码中,占用12个字节,而在Unicode编码中,占用16个字节。因为A和1、3、1这4个字符,在ANSI编码中只各占1个字节,而在Unicode编码中,是需要各占2个字节的。

2、cp936编码

cp936是微软自己发布的用在文件系统中的编码方式。而bg2312是中国国家标准。

目前Windows的内核已经采用Unicode编码,这样在内核上可以支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码,例如GBK,Windows不可能不支持现有的编码,而全部改用Unicode。Windows 使用代码页(code page)来适应各个国家和地区。code page可以被理解为前面提到的内码。GBK对应的code page是 CP936。

3、GB2312编码 GB2312(1980年)一共收录了7445个字符,包括6763个汉字和 682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。

ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。

2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。

4、Unicode编码

Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。 Unicode的学名是 "Universal Multiple-Octet Coded Character Set",简称为UCS。 UCS可以看作是"Unicode Character Set"的缩写。

UTF-8、UTF-7、UTF-16都是被广泛接受的方案。UTF-8的一个特别的好处是它与ISO- 8859-1完全兼容。UTF是 “UCS Transformat ion Format”的缩写。

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。  

UTF-8:UTF意为通用字集转换格式(Universal Character Set Transformation Format),UTF-8是Unicode的8位元格式。如果使用只能在同类位元组内支持8个位元的重要资料一类的旧式传输媒体,可选择UTF-8格式。

Unicode规范中推荐的标记字节顺序的方法是BOM。

在UCS编码中有一个叫做"ZERO WIDTH NO- BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO- BREAK SPACE"又被称作BOM。UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO
WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

Windows就是使用BOM来标记文本文件的编码方式的。

ANSI:        无格式定义; Unicode:       前两个字节为FFFE; Unicode big endian: 前两字节为FEFF;  UTF-8:        前两字节为EFBB;

三、实例应用

im中在线课程搜索功能(双字节转换成单字节)

数学 --》 %E6%95%B0%E5%AD%A6

代码:

//zhang20120228 在线课程的搜索功能,将unicode转换为utf8
void CSearchWndHC::UrlEncodeUtf8(LPCTSTR  pszUrl, LPTSTR  pResult, long * plLen)
{
	// TODO: Add your specialized code here.
	if(pszUrl == NULL)
	{
		//*pResult = 0;
		*plLen = 0;
		return ;
	}
	int iLen = lstrlen(pszUrl);
	if (pResult == 0)
	{
		*plLen = 0;
		return;
	}
	pResult[0]=0;
	int i = 0;
	BYTE j,k;
	BYTE* p=(BYTE* )pszUrl;
	while(*p)
	{
		if((*p <=_T('9') && *p >=_T('0'))||(*p <=_T('z') && *p >=_T('a'))||(*p
			<=_T('Z') && *p >=_T('A')))
		{
			pResult[i++]=*p++;
		}
		else
		{
			if(*p <0 ||*p >127)
			{
				j= *p/16;k=*p%16;

				if(j > 9) j+=_T('A')-10;

				else j+=48;

				if(k > 9) k+=_T('A')-10;

				else k+=48;

				pResult[i++]=_T('%');

				pResult[i++]=j;

				pResult[i++]=k;

				p++;

				j= *p/16;k=*p%16;

				if(j > 9) j+=_T('A')-10;

				else j+=48;

				if(k > 9) k+=_T('A')-10;

				else k+=48;

				pResult[i++]=_T('%');

				pResult[i++]=j;

				pResult[i++]=k;

				p++;

			}

			else
			{
				j= *p/16;k=*p%16;

				if(j > 9) j+=_T('A')-10;

				else j+=48;

				if(k > 9) k+=_T('A')-10;
				else k+=48;
				pResult[i++]=_T('%');
				pResult[i++]=j;
				pResult[i++]=k;
				p++;
			}
		}
	}
	pResult[i]=0;
	*plLen = i;
	//*ppResult = pResult;
}
//zhang20120228 在线课程的搜索功能,将unicode转换为utf8
LPTSTR  CSearchWndHC::translateTCHARToUTF_8(LPTSTR xmlStream, int len) 

{
	HRESULT hr;
	IMultiLanguage *pMultiLanguage=NULL;
	UINT  one=0;
	UINT  two=0;
	DWORD pdwMode=0;
	LPTSTR  m_setstr=NULL;
	LPTSTR  m_getstr=NULL;
	LPTSTR  finalTCHARBuffer=NULL ;
	CoInitialize(NULL);
	hr=CoCreateInstance(CLSID_CMultiLanguage,NULL,CLSCTX_ALL,IID_IMultiLanguage ,(void**)&pMultiLanguage);

	if( FAILED(hr))
	{
		return 0;
	}
	one=len;
	m_setstr=(LPTSTR )xmlStream;
	hr=pMultiLanguage->ConvertString(&pdwMode,COVS_0001,COVS_0030,(unsigned char*)m_setstr,&one,NULL,&two);
	//hr=pMultiLanguage->ConvertString(&pdwMode,20936,65001,(unsigned char*)m_setstr,&one,NULL,&two);

	if( FAILED(hr))

	{
		pMultiLanguage->Release();
		CoUninitialize();
		delete[] m_getstr;
		return 0;
	}
	m_getstr=new TCHAR[two + 1];
	memset( m_getstr, _T('\0'), two + 1 );
	//hr=pMultiLanguage->ConvertString(&pdwMode,20936,65001,(unsigned char*)m_setstr,&one,(unsigned char*)m_getstr,&two);
	hr=pMultiLanguage->ConvertString(&pdwMode,COVS_0001,COVS_0030,(unsigned char*)m_setstr,&one,(unsigned char*)m_getstr,&two);
	if( FAILED(hr))
	{
		pMultiLanguage->Release();
		CoUninitialize();
		delete[] m_getstr;
		return 0;
	}
	pMultiLanguage->Release();
	CoUninitialize();
	finalTCHARBuffer = new TCHAR[two+1];
	memset(finalTCHARBuffer,0,sizeof(finalTCHARBuffer));
	memcpy(finalTCHARBuffer,m_getstr,two+1);
	delete[] m_getstr;
	return finalTCHARBuffer;
	pMultiLanguage->Release();
	CoUninitialize();
	delete[] m_getstr;
	return 0;
}

urlencode函数

数学 --》 %CA%FD%D1%A7

//zhang20110804 新添加一个函数,赋值拼http地址串
CString CSearchWndHC::URLEncode(CString sIn)
{
	CString sOut;

	const int nLen = sIn.GetLength() + 1;

	register LPBYTE pOutTmp = NULL;
	LPBYTE pOutBuf = NULL;
	register LPBYTE pInTmp = NULL;
	LPBYTE pInBuf =(LPBYTE)sIn.GetBuffer(nLen);
	BYTE b = 0;

	//alloc out buffer
	pOutBuf = (LPBYTE)sOut.GetBuffer(nLen*3 - 2);//new BYTE [nLen  * 3];

	if(pOutBuf)
	{
		pInTmp   = pInBuf;
		pOutTmp = pOutBuf;

		// do encoding
		while (*pInTmp)
		{
			if(isalnum(*pInTmp))
				*pOutTmp++ = *pInTmp;
			else
				if(isspace(*pInTmp))
					*pOutTmp++ = '+';
				else
				{
					*pOutTmp++ = '%';
					*pOutTmp++ = toHex(*pInTmp>>4);
					*pOutTmp++ = toHex(*pInTmp%16);
				}
				pInTmp++;
		}
		*pOutTmp = '\0';
		//sOut=pOutBuf;
		//delete [] pOutBuf;
		sOut.ReleaseBuffer();
	}
	sIn.ReleaseBuffer();
	return sOut;
}

linux urlEncodeGb2312

数学 --》 %CA%FD%D1%A7

#include <stdio.h>
#include <IOSTREAM>
using namespace std;

typedef unsigned char BYTE;  

BYTE toHex(const BYTE &x)
{
    return x > 9 ? x -10 + 'A': x + '0';
}  

BYTE fromHex(const BYTE &x)
{
    return isdigit(x) ? x-'0' : x-'A'+10;
}  

string URLEncode(const string &sIn)
{
    string sOut;
    for( size_t ix = 0; ix < sIn.size(); ix++ )
    {
        BYTE buf[4];
        memset( buf, 0, 4 );
        if( isalnum( (BYTE)sIn[ix] ) )
        {
            buf[0] = sIn[ix];
        }
        //else if ( isspace( (BYTE)sIn[ix] ) ) //貌似把空格编码成%20或者+都可以
        //{
        //    buf[0] = '+';
        //}
        else
        {
            buf[0] = '%';
            buf[1] = toHex( (BYTE)sIn[ix] >> 4 );
            buf[2] = toHex( (BYTE)sIn[ix] % 16);
        }
        sOut += (char *)buf;
    }
    return sOut;
}

string URLDecode(const string &sIn)
{
    string sOut;
    for( size_t ix = 0; ix < sIn.size(); ix++ )
    {
        BYTE ch = 0;
        if(sIn[ix]=='%')
        {
            ch = (fromHex(sIn[ix+1])<<4);
            ch |= fromHex(sIn[ix+2]);
            ix += 2;
        }
        else if(sIn[ix] == '+')
        {
            ch = ' ';
        }
        else
        {
            ch = sIn[ix];
        }
        sOut += (char)ch;
    }
    return sOut;
} 

int main(int argc, char* argv[])
{
	printf("Hello World!\n");

	string str = "数学zhang";
	string out = URLEncode(str);
	string instr = URLDecode(out);

	cout<<out.c_str()<<endl;
	cout<<instr.c_str()<<endl;

	return 0;
}

时间: 2024-08-24 15:07:19

不同字符编码格式之间的转换的相关文章

Delphi字符串、PChar与字符数组之间的转换

来自:http://my.oschina.net/kavensu/blog/193719 ----------------------------------------------------------------- var s: string; p: pchar; a: array[1..20] of char; 1.字符串 ---> PChar p := PChar(s); 2.PChar ---> 字符串 s := p; 3.PChar ---> 字符数组 StrCopy(@a

《Python CookBook2》 第一章 文本 - 每次处理一个字符 &amp;&amp; 字符和字符值之间的转换

文本 - 总结: 什么是文本Python 中的string 类型是不可变类型.文本,一个字符的矩阵,每一个单独的文本快可以被缩进和组织起来. 基本的文本操作①解析数据并将数据放入程序内部的结构中:②将数据以某种方式转化为另一种相似的形式,数据本身发生了改变:③生成全新的数据 每次处理一个字符: 任务用每次处理一个字符的方式处理字符串. 解决方案可以创建一个列表,列表的子项是字符串的字符.代码如下: >>> thelist = list('thestring') >>>

字符串和字符数组之间的转换

package String; /* * 写了一个字符串和字符数组之间转换的例子 * 总结:将字符串转变为字符数组 :public char[] toCharArray() * 直接将一个字符数组变成一个字符串 public String (char[] value) 这个是构造函数啊,可以直接new 并为属性赋值啊. */ public class StringDemo2 { public static void main(String[] args) { String s = "hellow

python-day3-内置函数与字符字节之间的转换

1 #三元运算 2 1 if True else 0 3 >>>1 4 5 1 if False else 0 6 >>>0 7 8 #内置函数lambda 9 def f1(a1): 10 return a1+100 11 ret=f1(10) 12 print(ret) 13 >>>110 14 #相当于 15 f2=lambda a1:a1+100 16 ret2=f2(10) 17 print(ret2) 18 >>>110

字符编码之间的转换

VC中实现GB2312.BIG5.Unicode编码转换的方法 投稿:shichen2014 字体:[增加 减小] 类型:转载 时间:2014-07-21 这篇文章主要介绍了VC中实现GB2312.BIG5.Unicode编码转换的方法,该功能非常实用,需要的朋友可以参考下 本文主要以实例形式讨论了VC编译环境下,实现字符串和文件编码方式转换的方法,在linux下请使用Strconv来实现.具体方法如下: 一.文件编码格式转换 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14

python中的字符数字之间的转换函数

int(x [,base ])         将x转换为一个整数 long(x [,base ])        将x转换为一个长整数 float(x )               将x转换到一个浮点数 complex(real [,imag ])  创建一个复数 str(x )                 将对象 x 转换为字符串 repr(x )                将对象 x 转换为表达式字符串 eval(str )              用来计算在字符串中的有效Py

Java Int类型与字符,汉字之间的转换

/** * java 中的流主要是分为字节流和字符流 * 再一个角度分析的话可以分为输入流和输出流 * 输入和输出是一个相对的概念 相对的分别是jvm虚拟机的内存大小 * 从另一个角度讲Java或者用Java开发的其他软件只是一个工具而已 * 你可以从几个角度进行深入,一个是利用好工具,一个是改造工具,一个是制造工具 */ try { BufferedReader bufferedReader=new BufferedReader(new FileReader(new File("D:\\ES笔

DB2中字符、数字和日期类型之间的转换

DB2中字符.数字和日期类型之间的转换 一般我们在使用DB2或Oracle的过程中,经常会在数字<->字符<->日期三种类 型之间做转换,那么在DB2和Oracle中,他们分别是如何实现的呢?在Oracle这几个类型之间的转换是十分方便的,通过 to_char|to_date|to_number函数即可完成类型转换.本小节主要介绍DB2中的一些知识,从Oracle转过来的DBA或开发人 员,可以对比着学习. 数字型到字符型的转换 DB2中的col_a字段 字段类型 到字符类型的转换

怎样在Java中实现基本数据类型与字符之间的转换

摘要:在我们对Java的学习当中数据类型之间的转换,是我们常见的事,我们也都知道基本数据类型之间有自动转换和强制转换,在int   . short  . long .float .double之间的转换我们都比较清楚的吧,但我们也应该知道它们与字符串及字符型之间的类型转换又是怎样对,让我们一起来探讨一下它们的转换: 1.整形与字符型之间的数据类型转换: 一.int转换成char有两种方法: ① 是利用char的unicode编码 例:int num1 = 8; char ch1 = (char)