在使用ndk开发应用程序时,有时需要字符编码转换,这里使用开源库iconv进行字符编码转换,代码如下
#include <jni.h>
#include <string>
#include <iconv.h>
#include <iostream>
class HStringConverter
{
char *_buf;
size_t _bufSize;
public:
HStringConverter()
:_buf(nullptr), _bufSize(0)
{}
~HStringConverter()
{
delete [] _buf;
_buf = nullptr;
_bufSize = 0;
}
char *convertString(const char * fromCode, const char * toCode, const char * source)
{
size_t retlen = 0;
size_t inbytesleft = strlen(source);
if (!strncmp(fromCode, "UTF-16LE", 8))
{
inbytesleft = wcslen((wchar_t *)source) * 2;
}
size_t outbytesleft = inbytesleft * 4 + 2;
retlen = outbytesleft;
char *tmp = resize(outbytesleft);
char * inbuf = (char *)source;
char * outbuf = (char *)tmp;
iconv_t cd = iconv_open(toCode, fromCode);
size_t errorNo = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
retlen -= outbytesleft;
if (errorNo == -1)
{
memcpy(tmp, source, inbytesleft);
}
else
{
memset(tmp + retlen, 0, outbytesleft);
}
iconv_close(cd);
return tmp;
}
private:
char *resize(int newSize)
{
if (_bufSize < newSize)
{
delete [] _buf;
_bufSize = newSize;
_buf = new char[newSize];
}
memset(_buf, 0, newSize);
return _buf;
}
};
class GBK: public HStringConverter
{
const char *_gbk;
public:
GBK(const char *gbk)
:_gbk(gbk)
{ }
char *toUtf8()
{
return convertString("GBK", "UTF-8", _gbk);
}
wchar_t *toUnicode()
{
return (wchar_t *)convertString("GBK", "UTF-16LE", _gbk);
}
};
class Unicode: public HStringConverter
{
const wchar_t *_unicode;
public:
Unicode(const wchar_t *unicode)
:_unicode(unicode)
{
}
char *toGBK()
{
return convertString("UTF-16LE","GBK", (const char*)_unicode);
}
char *toUtf8()
{
return convertString("UTF-16LE","UTF-8", (const char*)_unicode);
}
};
class Utf8: public HStringConverter
{
const char *_utf8;
public:
Utf8(const char *utf8)
:_utf8(utf8)
{}
wchar_t *toUnicode()
{
return (wchar_t *)convertString("UTF-8", "UTF-16LE", _utf8);
}
char *toGBK()
{
return convertString("UTF-8", "GBK", _utf8);
}
};
extern "C"
jstring Java_com_irisking_attendserver_AttendServer_getName(JNIEnv *env, jobject thisz)
{
const char *name = "韩呈杰";
return env->NewStringUTF(GBK(name).toUtf8());
}
这里支持UTF-16LE(Unicode),UTF-8和GBK之间的编码相互转换。其中最后一个函数是使用示例。
Android NDK r9c中,iconv.h有一处bug,需修改后才可编译,否则在编译时会报错,修改如下:
//#ifdef __cplus_plus
//改为
#ifdef __cplusplus
} // extern "C"
#endif
完整的源代码,参见: Android NDK使用Iconv进行编码转换