不依赖任何系统API,用c语言实现gbk/utf8/unicode编码转换

汉字'我'
Unicode编码是 0x6211 0110 0010 00 010001
UTF8编码是 0xe68891 1110 0110 10 001000 100 010001
oxc0 11000000
0xE0 11100000
| Unicode符号范围 | UTF-8编码方式
n | (十六进制) | (二进制)
---+----------------------- -----------+--------------------------------------------------------------------------
1 | 0x00 - 0x7F | 0zzzzzzz
2 | 0x80 - 0x7FF | 110yyyyy 10zzzzzz
3 | 0x800 - 0xFFFF | 1110xxxx 10yyyyyy 10zzzzzz
--------------------------------------------------------------------------------------------------------------------
4 | 0x10000 - 0x1FFFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5 | 0x200000 - 0x3FFFFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 | 0x4000000 - 0x7FFFFFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

表 UTF-8的编码规则

一:unicode转utf8

'我'的unicode编码0x6211,二进制为:01100010 00010001
将二进制形式分割成3段为0110 001000
010001 (分别是高4位、中间的6位、最后的低6位)
unicode转utf8只需要这3段分别填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx yyyyyy zzzzzz
得utf8编码是0xe6889,二进制为: 11100110 10001000 100010001

int UnicodeToUtf8(char* pInput,char *pOutput)  
{  
	int len = 0; //记录转换后的Utf8字符串的字节数
	while (*pInput)
	{
		//处理一个unicode字符
		char low = *pInput;//取出unicode字符的低8位
		pInput++;
		char high = *pInput;//取出unicode字符的高8位
		int w=high<<8;
		unsigned  wchar = (high<<8)+low;//高8位和低8位组成一个unicode字符,加法运算级别高

		if (wchar <= 0x7F ) //英文字符
		{   
			pOutput[len] = (char)wchar;  //取wchar的低8位
			len++;
		}  
		else if (wchar >=0x80 && wchar <= 0x7FF)  //可以转换成双字节pOutput字符
		{  
			pOutput[len] = 0xc0 |((wchar >> 6)&0x1f);  //取出unicode编码低6位后的5位,填充到110yyyyy 10zzzzzz 的yyyyy中
			len++;
			pOutput[len] = 0x80 | (wchar & 0x3f);  //取出unicode编码的低6位,填充到110yyyyy 10zzzzzz 的zzzzzz中
			len++;
		}  
		else if (wchar >=0x800 && wchar < 0xFFFF)  //可以转换成3个字节的pOutput字符
		{  
			pOutput[len] = 0xe0 | ((wchar >> 12)&0x0f);  //高四位填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx
			len++;
			pOutput[len] = 0x80 | ((wchar >> 6) & 0x3f);  //中间6位填入1110xxxx 10yyyyyy 10zzzzzz中的yyyyyy
			len++;
			pOutput[len] = 0x80 | (wchar & 0x3f);  //低6位填入1110xxxx 10yyyyyy 10zzzzzz中的zzzzzz
			len++;
		}  

		else //对于其他字节数的unicode字符不进行处理
		{
			return -1;
		}
		pInput ++;//处理下一个unicode字符
	}
	//utf8字符串后面,有个\0
	pOutput [len]= 0;
	return len;  
}  

二:utf8转unicode

utf8二进制形式为1110xxxx 10yyyyyy 10zzzzzz
'我'的utf8编码0xe6889,二进制为:1110 0110 10 001000 10 0010001
分别提取里面的xxxx yyyyyy zzzzzz,然后组合成xxxxyyyy yyzzzzzz,
xxxxyyyy就是unicode的高8位,yyzzzzzz就是unicode的低8位

/*************************************************************************************************
* 将UTF8编码转换成Unicode(UCS-2LE)编码  低地址存低位字节
* 参数:
*    char* pInput     输入字符串
*    char*pOutput   输出字符串
* 返回值:转换后的Unicode字符串的字节数,如果出错则返回-1
**************************************************************************************************/
//utf8转unicode
int Utf8ToUnicode(char* pInput,char* pOutput)
{
	int outputSize = 0; //记录转换后的Unicode字符串的字节数

	while (*pInput)
	{
		if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字)
		{
			*pOutput = *pInput;
			 pOutput++;
			*pOutput = 0; //小端法表示,在高地址填补0
		}
		else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
		{
			char high = *pInput;
			pInput++;
			char low = *pInput;
			if ((low & 0xC0) != 0x80)  //检查是否为合法的UTF8字符表示
			{
				return -1; //如果不是则报错
			}

			*pOutput = (high << 6) + (low & 0x3F);
			pOutput++;
			*pOutput = (high >> 2) & 0x07;
		}
		else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符
		{
			char high = *pInput;
			pInput++;
			char middle = *pInput;
			pInput++;
			char low = *pInput;
			if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
			{
				return -1;
			}
			*pOutput = (middle << 6) + (low & 0x3F);//取出middle的低两位与low的低6位,组合成unicode字符的低8位
			pOutput++;
			*pOutput = (high << 4) + ((middle >> 2) & 0x0F); //取出high的低四位与middle的中间四位,组合成unicode字符的高8位
		}
		else //对于其他字节数的UTF8字符不进行处理
		{
			return -1;
		}
		pInput ++;//处理下一个utf8字符
		pOutput ++;
		outputSize += 2;
	}
	//unicode字符串后面,有两个\0
	*pOutput = 0;
	 pOutput++;
	*pOutput = 0;
	return outputSize;
}
//一个调用示例
int main(int argc,char** argv)
{
	//汉字“我”的UTF8编码是0xe68891,Unicode编码是 0x6211

	//1、unicode转utf8
	char unicodeStr[3]={0x11,0x62,0x00};//我的unicode编码是0x6211,按低地址存低位字节
	char* utf8Str = new char [5];
	memset(utf8Str,5);
	int num = UnicodeToUtf8(unicodeStr,utf8Str);

	unsigned char* p = (unsigned char*)utf8Str;   
	for (int i = 0; i < num; i++)
	{
		printf("%0x",*p);
		p++;
	}//输出e68891
	printf("\n");
	delete utf8Str;

	//2、utf8转unicode
	//char utf8Str[4] = {0xe6,0x88,0x91,0x00}; 
	//char* unicodeStr = new char[8];
	//memset(unicodeStr,8);
	//int num = Utf8ToUnicode(utf8Str,unicodeStr);
	//if (num == -1)
	//{
	//	printf("Error!\n");
	//}
	//else
	//{
	//       unsigned char* p = (unsigned char*)unicodeStr;
	//	for (int i = 0; i < num; i++)
	//	{
	//		printf("%0x",*p);
	//		p++;
	//	}//输出1162
	//	printf("\n");
	//}
	//delete unicodeStr;

	return 0;
} 

三、gbk与unicode互转


参照博客:

http://blog.csdn.net/tge7618291/article/details/7599902 http://www.ithao123.cn/content-1832906.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结