PC版本游戏--cocos2d-x中文乱码解决办法(GBK到UTF-8编码)及其fatal error: iconv\iconv.h: No such file or directory问题

时间:2023-01-28 08:41:40

<1>原因:这是因为VC采用GBK编码,而cocos2d-x采用UTF-8编码,编码方法不一致造成的。


<2>解决办法:

添加libiconv.lib。步骤:引用-->配置属性-->连接器-->输入-->附加依赖项   添加libiconv.lib


<3>将iconv.h添加到Classes下面。其中iconv.h的内容如下:

/* Copyright (C) 1999-2003 Free Software Foundation, Inc.
   This file is part of the GNU LIBICONV Library.

   The GNU LIBICONV Library is free software; you can redistribute it
   and/or modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   The GNU LIBICONV Library is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU LIBICONV Library; see the file COPYING.LIB.
   If not, write to the Free Software Foundation, Inc., 59 Temple Place -
   Suite 330, Boston, MA 02111-1307, USA.  */

/* When installed, this file is called "iconv.h". */

#ifndef _LIBICONV_H
#define _LIBICONV_H

#define _LIBICONV_VERSION 0x0109    /* version number: (major<<8) + minor */
extern int _libiconv_version;       /* Likewise */

/* We would like to #include any system header file which could define
   iconv_t, 1. in order to eliminate the risk that the user gets compilation
   errors because some other system header file includes /usr/include/iconv.h
   which defines iconv_t or declares iconv after this file, 2. when compiling
   for LIBICONV_PLUG, we need the proper iconv_t type in order to produce
   binary compatible code.
   But gcc's #include_next is not portable. Thus, once libiconv's iconv.h
   has been installed in /usr/local/include, there is no way any more to
   include the original /usr/include/iconv.h. We simply have to get away
   without it.
   Ad 1. The risk that a system header file does
   #include "iconv.h"  or  #include_next "iconv.h"
   is small. They all do #include <iconv.h>.
   Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It
   has to be a scalar type because (iconv_t)(-1) is a possible return value
   from iconv_open().) */

/* Define iconv_t ourselves. */
#undef iconv_t
#define iconv_t libiconv_t
typedef void* iconv_t;

/* Get size_t declaration. */
#include <stddef.h>

/* Get errno declaration and values. */
#include <errno.h>
/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS,
   have EILSEQ in a different header.  On these systems, define EILSEQ
   ourselves. */
#ifndef EILSEQ
/* Igor: called upon EILSEQ from glibc, since autogeneration of this header
    on Windows didn't do the job. */
/* #define EILSEQ @EILSEQ@ */
#define EILSEQ 84
#endif


#ifdef __cplusplus
extern "C" {
#endif


/* Allocates descriptor for code conversion from encoding `fromcode' to
   encoding `tocode'. */
#ifndef LIBICONV_PLUG
#define iconv_open libiconv_open
#endif
extern iconv_t iconv_open (const char* tocode, const char* fromcode);

/* Converts, using conversion descriptor `cd', at most `*inbytesleft' bytes
   starting at `*inbuf', writing at most `*outbytesleft' bytes starting at
   `*outbuf'.
   Decrements `*inbytesleft' and increments `*inbuf' by the same amount.
   Decrements `*outbytesleft' and increments `*outbuf' by the same amount. */
#ifndef LIBICONV_PLUG
#define iconv libiconv
#endif
extern size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);

/* Frees resources allocated for conversion descriptor `cd'. */
#ifndef LIBICONV_PLUG
#define iconv_close libiconv_close
#endif
extern int iconv_close (iconv_t cd);


#ifndef LIBICONV_PLUG

/* Nonstandard extensions. */

/* Control of attributes. */
#define iconvctl libiconvctl
extern int iconvctl (iconv_t cd, int request, void* argument);

/* Requests for iconvctl. */
#define ICONV_TRIVIALP            0  /* int *argument */
#define ICONV_GET_TRANSLITERATE   1  /* int *argument */
#define ICONV_SET_TRANSLITERATE   2  /* const int *argument */
#define ICONV_GET_DISCARD_ILSEQ   3  /* int *argument */
#define ICONV_SET_DISCARD_ILSEQ   4  /* const int *argument */

/* Listing of locale independent encodings. */
#define iconvlist libiconvlist
extern void iconvlist (int (*do_one) (unsigned int namescount,
                                      const char * const * names,
                                      void* data),
                       void* data);

/* Support for relocatable packages.  */

/* Sets the original and the current installation prefix of the package.
   Relocation simply replaces a pathname starting with the original prefix
   by the corresponding pathname with the current prefix instead.  Both
   prefixes should be directory names without trailing slash (i.e. use ""
   instead of "/").  */
extern void libiconv_set_relocation_prefix (const char *orig_prefix,
                        const char *curr_prefix);

#endif


#ifdef __cplusplus
}
#endif


#endif /* _LIBICONV_H */

 

<4>添加文件Tool.h和Tool.cpp,内容如下:

Tool.h

#ifndef _Tool_
#define _Tool_

#include "cocos2d.h"
#include "iconv.h"

#include <iostream>
#include <string.h>
int code_convert(const char *from_charset, const char *to_charset, const char *inbuf, size_t inlen, char *outbuf, size_t outlen);
/*UTF8תΪGB2312*/  
std::string u2a(const char *inbuf);
/*GB2312תΪUTF8*/  
std::string a2u(const char *inbuf);


#endif

 

Tool.cpp

#include "Tool.h"

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

/*UTF8תΪGB2312*/  
std::string u2a(const char *inbuf)  
{  
	size_t inlen = strlen(inbuf);  
	char * outbuf = new char[inlen * 2 + 2];  
	std::string strRet;  
	if(code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)  
	{  
		strRet = outbuf;  
	}  
	delete [] outbuf;  
	return strRet;  
}  

/*GB2312תΪUTF8*/  
std::string a2u(const char *inbuf)  
{  
	size_t inlen = strlen(inbuf);  
	char * outbuf = new char[inlen * 2 + 2];  
	std::string strRet;  
	if(code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)  
	{  
		strRet = outbuf;  
	}  
	delete [] outbuf;  
	return strRet;  
}  

<4>使用a2u即可。

<5>判断字段文本是否是utf8格式,是的话,不需要转码,不是就需要转码.
#ifndef _UTFUtils_
#define _UTFUtils_

class MyUTF
{
public:
	static bool isUTF8(const char *pText, int nLen)
	{
		// octets to go in this UTF-8 encoded character
		unsigned long dwOctets;
		unsigned char chr;
		bool bAllAscii= true;

		// 循环检测
		dwOctets = 0;
		for (int i = 0; i < nLen; i++)
		{
			// 取出当前字符
			chr = *(pText + i);

			if ((chr & 0x80) != 0)
				// 当前字符不是 ascii
				bAllAscii = false;

			if (dwOctets == 0)
			{
				// 7 bit ascii after 7 bit ascii is just fine.  Handle start of encoding case

				if (chr >= 0x80)
				{
					// count of the leading 1 bits is the number of characters encoded

					do
					{
						chr <<= 1;
						dwOctets++;
					} while ((chr & 0x80) != 0);

					// count includes this character
					dwOctets--;                
					//if (dwOctets == 0)
					if (dwOctets < 2)
						// must start with 11xxxxxx
						return false;
				}
			}
			else
			{
				// non-leading bytes must start as 10xxxxxx
				if ((chr & 0xC0) != 0x80)
					return false;

				// processed another octet in encoding
				dwOctets--;
			}
		}

		// End of text.  Check for consistency

		if (dwOctets > 0)
			// anything left over at the end is an error
			return false;

		if (bAllAscii)
			// Not utf-8 if all ascii.  Forces caller to use code pages for conversion
			return false;

		return true;
	}

};


#endif
引用的话使用类似于:
#include "C:/cocos2d-x-2.2.5/cocos2d-x-2.2.5/projects/IGuanGanKing_2014_10_29/Classes/UTFUtils.h"
的绝对路径.
<6>UILabel
void Label::setText(const std::string& text)
{
	if(!MyUTF::isUTF8(text.c_str(), text.size()))
	    _labelRenderer->setString(a2u(text.c_str()).c_str()); 
	else
	    _labelRenderer->setString(text.c_str()); 
    labelScaleChangedWithSize();
}
<7>UILabelBMFont
void LabelBMFont::setText(const char* value)
{
    if (!value)
	{
		return;
	}
    _stringValue = value;
    if (!_fntFileHasInit)
    {
        return;
    }
	const std::string& str = value;
	if(!MyUTF::isUTF8(str.c_str(), str.size()))
        _labelBMFontRenderer->setString(a2u(value).c_str());
	else
		_labelBMFontRenderer->setString(value);
    labelBMFontScaleChangedWithSize();
}
<8>
注意一个问题:当unicode和utf8一起混编时,就不可以再执行setText了,会出现显示不出来.例如:
btn->setTitleText(toStr("签到%i次",info->getMaxNum())->getCString());
info->getMaxNum()是从服务器读取的,是utf8编码,而vs本身带的字体"签到","次"是Unicode,所以整体在一起,就出现乱码了.
解决方案:
string signStr = a2u("签到");
signStr += CCString::createWithFormat("%i", info->getMaxNum())->getCString();
signStr += a2u("次");
 
 对应关系: 
Unicode<-->GBK
ANSI<-->utf8