由于项目需要,需要将GB2312格式的编码转换成UTF-8格式,用android本身的jni函数中的转换格式总是乱码,如果底层发上来的数 据,通过 jni的NewStringUTF()函数将数据转换成utf-8,但是发送到上层显示依然是乱码,也就是说NewStringUTF函数没有起 作 用,linux下有个iconv命令可以转换编码格式,于是想把iconv移植到android上,调用iconv中的函数来转换编码格式。
iconv源码下载
首先,下载iconv代码,将下载的代码解压,进入解压后的源码目录,现在linux环境下进行配置,执行 comfigure脚本,产生linux下config.h文件,因为config.h里定义了很多linux平台下的宏,
编译方法:
首先执行./configure --build=x86_64-pc-linux-gnu --host=arm-linux-eabi
然后执行make,然后在源码目录下创建一个Android.mk文件通过android来编译。
Android.mk写法
LOCAL_PATH:= $(callmy-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libiconv
LOCAL_CFLAGS := \
-Wno-multichar \
-DANDROID \
-DLIBDIR="c" \
-DBUILDING_LIBICONV \
-DIN_LIBRARY
LOCAL_SRC_FILES := \
libcharset/lib/localcharset.c \
lib/iconv.c \
lib/relocatable.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/libcharset \
$(LOCAL_PATH)/lib \
$(LOCAL_PATH)/libcharset/include \
$(LOCAL_PATH)/srclib
include $(BUILD_SHARED_LIBRARY)
将你写的代码放到android源码中,可以放到externl目录下,这样你就可以使用android的编译环境编译你的代码了
可以使用mm命令编译。这样会编译生成一个动态库libiconv.so
编译完后会放到 out/target/product/你的产品名/system/lib文件中
在你的代码中用到iconv_open() iconv()函数时需要在你的代码中加上编译出来的libiconv.so动态库
Android.mk文件写法
LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS = eng
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
main.c \
list.c \
serial.c \
interface.c \
communication.c
LOCAL_C_INCLUDES += \ //这里是引用iconv源码中的头文件,你可以把iconv源码中的include libcharset
$(LOCAL_PATH)/include \ lib libcharset/include srclib 等目录放到你的代码中
$(LOCAL_PATH)/libcharset \
$(LOCAL_PATH)/lib \
$(LOCAL_PATH)/libcharset/include \
$(LOCAL_PATH)/srclib
LOCAL_SHARED_LIBRARIES := libiconv //这里是引用libiconv.so动态库,
LOCAL_MODULE :=ubox
LOCAL_CFLAGS := -O0 -g
LOCAL_LDLIBS := -lpthread
include $(BUILD_EXECUTABLE)
编译时遇到的错误 libcharset/lib/localcharset.c:51:24: error: langinfo.h: No such file or directory
解决方法:
修改目录文件libcharset/config.h的宏定义,禁止该宏定义:
/* Define if you haveand nl_langinfo(CODESET). */
#define HAVE_LANGINFO_CODESET 0
报“c undeclaired”错误
解决方法:
修改文件/libcharset/lib/localcharset.c中函数get_charset_aliases (void)
搜索:int c;
把该变量定义放到该函数的开始处。
字符编码转换简单例子:
iconv_t iconv_open(const char *tocode, const char *fromcode);
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
int iconv_close(iconv_t cd);
iconv_open函数用来打开一个编码转换的流,
iconv函数的作用是实际进行转换,
iconv_close函数的作用就是关闭这个流。
实际用法参见下面的例子,下面是一个将UTF-8码转换成GBK码的例子,我们假设已经有了一个uft8编码的输入缓冲区inbuf以及这个缓冲区的长度inlen。
iconv_t cd = iconv_open( "GBK", "UTF-8");
char *outbuf = (char *)malloc(inlen * 4 );
bzero( outbiuf, inlen * 4);
char *in = inbuf;
char *out = outbuf;
size_t outlen = inlen *4;
iconv(cd, &in, (size_t *)&inlen, &out,&outlen);
outlen = strlen(outbuf);
printf("%s\n",outbuf);
free(outbuf);
iconv_close(cd);
非常值得注意的地方是:iconv函数会修改参数in和参数out指针所指向的地方,也就是说,在调用iconv函数之前,
我们的in和inbuf指针以及out和outbuf指针指向的是同一块内存区域,但是调用之后out指针所指向的地方就不是outbuf了,
同理in指针。所以要 char *in = inbuf; char *out = outbuf;
另存一下,使用或者释放内存的时候也要使用原先的那个指针outbuf和inbuf。
iconv -f GB2312 -t UTF-8 gb1.txt >gb2.txt 将gb1里的编码从GB2312转化成UTF-8 并重定向到gb2.txt