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

时间:2023-01-28 08:42:04

<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