[cocos2dx]在cocos2dx中使用iconv库解决中文乱码

iconv的作用是将文本在多种国际编码格式之间进行转换。

文件"iconv.h"。iconv命令可以将一种已知的字符集文件转换成另一种已知的字符集文件
目前版本为2.3.26,支持的内码包括:Unicode相关编码,如UTF-8、UTF-16等等,各国采用的ANSI编码,其中包括GB2312、BIG5等中文编码方式。
作为编程接口的iconv包括3个函数

  • iconv_open函数用于初始化用于转换的内部缓冲区,指明需要从何种编码方式转换到哪一种。
  • iconv函数进行实际的转换,需要给出两个间接缓冲区指针和剩余字节数指针。该函数需要更新所有相关信息,因此将不可改写的指针传递给iconv是错误的。
  • iconv_close函数释放iconv_open函数的缓冲区。

Convert.h

#ifndef _Convert_H_
#define _Convert_H_
#include <vector>
#include <string>

namespace utility
{
	int utf8_len(std::string utf8);
	std::string a_u8(std::string gbk);
	std::string u8_a(std::string utf8);
} 

#endif // _Convert_H_

Convert.cpp

#include "Convert.h"
#include "cocos2d.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "win32-specific\icon\include\iconv.h"
//#pragma comment(lib,"libiconv.lib")
#else
#include <iconv.h>
#endif

//////////////////////////////////////////////////////////////////////////

/**
 * 计算utf8字符串长度
 * @param utf8 utf8字符串 
 * @return 字符串长度
 */
int utf8_len(const char *utf8) 
{
	int i = 0,j = 0;
	while (utf8[i]) {
		if ((utf8[i] & 0xc0) != 0x80) j++;
		i++;
	}
	return j;
}

int utf8_cmp(const char* str1,const char* str2)
{
    unsigned int len1=(unsigned int)strlen((char*)str1);   
    unsigned int len2=(unsigned int)strlen((char*)str2);   
    unsigned int len = (len1<len2) ? len1 : len2;   
   
    int ret = memcmp(str1,str2,len);   
    if(ret == 0){   
        if(len1 > len2) ret = 1;   
        else if(len1 < len2) ret = -1;   
    }   
    return ret;   
}

/**
 * 计算ucs2字符串长度
 * @param ucs2 ucs2字符串 
 * @return 字符串长度
 */
int ucs2_len(const unsigned short* ucs2)
{
	int i = 0;
	while (ucs2[i] != 0)
	{
		char c0 = ucs2[i]&0xff;
		char c1 = ucs2[i]>>8&0xff;

		if (c0 == '\0' && c1 == '\0')
			break;
		++i;
	}

	return i;
}

/////////////////////////////////////////////////////////////////////////////
int code_convert(const char *from_charset,const char *to_charset,const char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	iconv_t cd;
	const char *temp = inbuf;
	const char **pin = &temp;
	char **pout = &outbuf;
	memset(outbuf,outlen);
	cd = iconv_open(to_charset,from_charset);
	if(cd==0) return -1;
	if(-1==iconv(cd,pin,&inlen,pout,&outlen)) return -1;
	iconv_close(cd);
	return 0;
#endif
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
	iconv_t cd;
	const char *temp = inbuf;
	const char **pin = &temp;
	char **pout = &outbuf;
	memset(outbuf,(char **)(pin),&outlen)) return -1;
	iconv_close(cd);
	return 0;
#endif
	return 0;
}

namespace utility
{
	/**
	 * 计算utf8字符串长度
	 * @param utf8 utf8字符串 
	 * @return 字符串长度
	 */
	int utf8_len(std::string utf8) 
	{
		return strlen(utf8.c_str());
	}
	int IsTextUTF8(const char* str,unsigned int  length)  
	{  
		return 0;
		unsigned int i;  
		unsigned long nBytes=0;//UFT8可用1-6个字节编码,ASCII用一个字节  
		unsigned char chr;  
		int bAllAscii=1; //如果全部都是ASCII,说明不是UTF-8  
		for(i=0;i<length;i++)  
		{  
			chr= *(str+i);  
			if( (chr&0x80) != 0 ) // 判断是否ASCII编码,如果不是,说明有可能是UTF-8,ASCII用7位编码,但用一个字节存,最高位标记为0,o0xxxxxxx  
				bAllAscii= 0;  
			if(nBytes==0) //如果不是ASCII码,应该是多字节符,计算字节数  
			{  
				if(chr>=0x80)  
				{  
					if(chr>=0xFC&&chr<=0xFD)  
						nBytes=6;  
					else if(chr>=0xF8)  
						nBytes=5;  
					else if(chr>=0xF0)  
						nBytes=4;  
					else if(chr>=0xE0)  
						nBytes=3;  
					else if(chr>=0xC0)  
						nBytes=2;  
					else  
					{  
						return 0;  
					}  
					nBytes--;  
				}  
			}  
			else //多字节符的非首字节,应为 10xxxxxx  
			{  
				if( (chr&0xC0) != 0x80 )  
				{  
					return 0;  
				}  
				nBytes--;  
			}  
		}  
		if( nBytes > 0 ) //违返规则  
		{  
			return 0;  
		}  
		if( bAllAscii ) //如果全部都是ASCII,说明不是UTF-8  
		{  
			return 0;  
		}  
		return 1;  
	}
	std::string a_u8(std::string gbk)
	{
		size_t inlen = strlen(gbk.c_str());
		if (inlen <= 0)
		{
			return std::string();
		}
		char * outbuf = new char[inlen * 4+2];
		std::string strRet = gbk;
		if(code_convert("gbk","utf-8",gbk.c_str(),inlen,outbuf,inlen * 4+2 ) == 0)
		{
			strRet = outbuf;
		}
		delete [] outbuf;
		return strRet;
	}
	std::string u8_a(std::string utf8)
	{
		size_t inlen = strlen(utf8.c_str());
		if (inlen <= 0)
		{
			return "";
		}
		char * outbuf = new char[inlen * 4+2];
		std::string strRet = utf8;
		if(code_convert("utf-8","gbk",utf8.c_str(),inlen*4+2) == 0)
		{
			strRet = outbuf;
		}
		else
		{
			strRet = "Error";
		}
		delete [] outbuf;
		return strRet;
	}
}

Mac下系统自带iconv.h文件

NDK自带的iconv,查看 android-ndk-r9d/sources/android/support/include/iconv.h
在Android.mk中加入
LOCAL_WHOLE_STATIC_LIBRARIES += android_support
$(call import-module,android/support)

编译android包,cocos compile -p android,就不会报iconv.h文件找不到的问题了。

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...