一、ICU4C及ucnv_convert概述

如果是在java层,有String类可以很好的转换各种编码,在ndk下面就没有现成的公开的工具,不过可以用icu4c。

ICU4C 是IBM的国际化开发组件ICU的C语言实现版本。在android系统里也有实现。ndk里面并没有公开可用的api,需要自己加载动态库来调用转换函数。

android下icu库路径为"/system/lib/libicuuc.so",主要用到的转换函数为ucnv_convert_*。这里的星号是根据版本的不同函数名也不一样,通常关联如下。函数名不同,导致程序的跨平台出现了问题,本文主要介绍如何在不同版本下统一使用ucnv_convert函数。

android版本号 ucnv_convert函数名
android2.1 ucnv_convert_3_8
android2.2 ucnv_convert_4_2
android2.3 ucnv_convert_44
android4.0 ucnv_convert_46
android4.1 ucnv_convert_47
android4.2 ucnv_convert_48
android4.3 ucnv_convert_50
android4.4 ucnv_convert_51
android7.0 ucnv_convert_56

二、函数原型及参数定义

int32_t ucnv_convert(const char *outEcd, const char *inEcd,char *outBuf, int32_t outLen,const char *inBuf, int32_t inLen,int32_t *errCode);
outEcd:目标编码格式,是输出的字符编码格式;
inEcd:原字符编码格式,是输入的字符编码格式;
outBuf:存放转换出来的字符的输出缓冲区;
outLen:outBuf输出缓冲区的大小;
inBuf:要转换的字符串指针;
inBuf:输入字符串的大小;
errCode:错误编码,该值不能为空;
返回值:整个源串inBuf转换后的字节数,该值不含'\0'结尾的长度,不受outBuf、outLen影响。

outLen与转换所需空间的关系

1.如果outLen小于转换所需空间:

1. outBuf 中会填充 outLen 所指定的转换的字节数,并且不会有 0 填充 outBuf 的结尾
2. errCode 会被置为 U_BUFFER_OVERFLOW_ERROR

2.如果outLen等于转换所需空间:

1. outBuf 中会填充 outLen 所指定的转换的字节数,并且不会有 0 填充 outBuf 的结尾
2. errCode 会被置为 U_STRING_NOT_TERMINATED_WARNING

3.如果outLen大于转换所需空间:

1. outBuf 中会填充返回值的字节数,outBuf[返回值] 处被填为 0 表示 outBuf 字符串结束
2. errCode会被置为 U_ZERO_ERROR

4.其他:

outBuf 可被置为 NULL (当然此时outLen应该为0),此时:
 1. errCode 会被置为 U_BUFFER_OVERFLOW_ERROR
 2. 可以使用这种方法来计算转换所需空间,但感觉不是太值

三、使用例程

#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <android/log.h>#define LOG_TAG "LOG"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define SourceFile "jni/xxx.cpp"
typedef int32_t (*TUCNVCONVERT) (const char *outEcd, const char *inEcd,char *outBuf, int32_t outLen,const char *inBuf, int32_t inLen,int32_t *errCode);void *handle = NULL;
TUCNVCONVERT ucnv_convert = NULL;void init() {const char *path = "/system/lib/libicuuc.so";int libFile = open(path, O_RDONLY);if (libFile < 0) {LOGE("%s(%d): ", SourceFile, 73);LOGE("open(%s): %s\n", path, strerror(errno));return;}struct stat libBuf;if (fstat(libFile, &libBuf) < 0) {LOGE("%s(%d): ", SourceFile, 80);LOGE("fstat(%mProgress): %s\n", libFile, strerror(errno));return;}void *lib = mmap(NULL, (size_t) libBuf.st_size, PROT_READ, MAP_PRIVATE, libFile, 0);if (lib == MAP_FAILED) {LOGE("%s(%d): ", SourceFile, 85);LOGE("mmap(): %s\n", strerror(errno));return;}handle = dlopen(path, RTLD_LAZY);char *libName = (char*) memmem(lib, (size_t) libBuf.st_size, "ucnv_convert_", 13);if (libName == NULL) {LOGE("%s(%d): ", SourceFile, 93);LOGE("ucnv_convert() not find\n");return;}ucnv_convert = (TUCNVCONVERT) dlsym(handle, libName);if (ucnv_convert == NULL) {LOGE("%s(%d): ", SourceFile, 99);LOGE("dlsym(%s) return null\n", libName);return;}munmap(lib, (size_t) libBuf.st_size);
}//utf-8,gb2312,ucs4
//utf-8:  一个英文字母或者是数字占用一个字节,汉字占3个字节
//gb2312: 一个英文字母或者是数字占用一个字节,汉字占2个字节
int32_t dl_icuuc_gbk2utf8(char *outbuf, int32_t buflen, const char *instring, int32_t inlen)
{int32_t iret = 0;if (outbuf != 0 && instring != 0){if (ucnv_convert != 0){int32_t err_code = 0;iret = ucnv_convert("utf-8", "gb2312",outbuf, buflen,instring, inlen,&err_code);}}return iret;
}
int32_t dl_icuuc_utf82gbk(char *outbuf, int32_t buflen, const char *instring, int32_t inlen)
{int32_t iret;iret = 0;if (outbuf != 0 && instring != 0){if (ucnv_convert != 0){int32_t err_code = 0;iret = ucnv_convert("gb2312", "utf-8",outbuf, buflen,instring, inlen,&err_code);}}return iret;
}
int32_t dl_icuuc_unicode2utf8(char *outbuf, int32_t buflen, const unsigned short *instring, int32_t inlen)
{int32_t iret;iret = 0;if (outbuf != 0 && instring != 0){if (ucnv_convert != 0){int32_t err_code = 0;iret = ucnv_convert("utf-8", "ucs4",outbuf, buflen,(const char *)instring, inlen*sizeof(unsigned short)/sizeof(char),&err_code);}}return iret;
}
int32_t dl_icuuc_utf82unicode(unsigned short *outbuf, int32_t buflen, const char *instring, int32_t inlen)
{int32_t iret;iret = 0;if (outbuf != 0 && instring != 0){if (ucnv_convert != 0){int32_t err_code = 0;iret = ucnv_convert("ucs4", "utf-8",(char *)outbuf, buflen*sizeof(unsigned short)/sizeof(char),instring, inlen,&err_code);}}return iret;
}

Android NDK 字符编码转换及icu库ucnv_convert函数不同版本的统一使用方法相关推荐

  1. android 使用icon进行字符编码转换

    在使用ndk开发应用程序时,有时需要字符编码转换,这里使用开源库icon进行字符编码转换,代码如下 char * convertString(const char * fromCode, const ...

  2. Android字符编码转换,GBK转UTF-8

    Android字符编码转换,GBK转UTF-8 网上看了很多都不能用,最后看到这个方法,很靠谱,分享给大家! String str; str = new String(str.getBytes(&qu ...

  3. 字符编码转换类(支持多国语言)

    头文件StrConvertor.h /* * 字符编码转换库,支持多国语言. */ #pragma once #include <string>class CStrConvertor { ...

  4. iconv 判断字符编码_iconv字符编码转换全攻略

    iconv(http://www.gnu.org/software/libiconv/)是一个开源的字符编码转换库,可以"方便"的完成几乎所有的编码转换工作.说简单是因为,它常用的 ...

  5. c语言使用iconv函数实现字符编码转换

    c语言使用iconv函数实现字符编码转换 linux下提供了iconv库来实现字符编码转换,先介绍下命令行: iconv [-f encoding] [-t encoding] [inputfile ...

  6. 《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》

    维护一个交易系统,交易记录表tradelog包含交易流水号(tradeid).交易员id(operator).交易时间(t_modified)等字段. create table 'tradelog' ...

  7. Qt中的字符编码转换:UTF8、Unicode、GBK、ASCII、16进制字符、16进制数值

    文章目录 前言 简述 ASCII GBK Unicode UTF-8 应用场景 开发环境 编码转换 16进制数值转换为16进制字符 16进制数值转化为字符串 16进制字符串转换为Unicode字符串 ...

  8. iconv()和mb_conver_encoding()字符编码转换函数

    2019独角兽企业重金招聘Python工程师标准>>> 一. `string iconv ( string $in_charset , string $out_charset , s ...

  9. 【转】Vim 字符编码转换

    如果只是要简单的转换文件编码,打开后          :set fileencodings=utf-8 ,然后 w (存盘)一下即可转化为 utf8 格式,       :set fileencod ...

最新文章

  1. 鸟哥的Linux私房菜(基础篇)-第三章、主机规划与磁盘分区(三.4. 重点回顾)
  2. Python学习系列day5-python基础
  3. 【渝粤题库】广东开放大学 会展概论 形成性考核
  4. mysql——decimal类型与decimal长度
  5. 收藏 | 使用Pytorch从头实现Canny边缘检测
  6. GDI+中发生一般性错误的解决办法(转帖)
  7. 应用开发专家一席谈:开发低代码,上手低门槛,AppCube使能Citizen Developer,人人都是开发者
  8. 解密flash播放器
  9. Windows驱动开发技术详解——经典书评
  10. struts2拦截器interceptor的三种配置方法
  11. 10分钟掌握运输问题(一)
  12. 【终终极版】linux(Ubuntu)下wineQQ的安装办法
  13. 工业机器人技术基础及其应用总结
  14. 单维度量表验证性因子分析_探索性因子分析(EFA)和验证性因子分析(CFA)
  15. 简简单单几行Python代码就能暴力破解网站登录密码,真有这么强吗?
  16. 微信刷票python代码_微信刷票漏洞详解, Python脚本实现一秒破万!
  17. 设置手机最小宽度为1000,无限重启怎么办
  18. QGIS进行坐标转换
  19. 我的 Chrome 插件集
  20. 九点标定和旋转中心标定后旋转点的计算

热门文章

  1. mysql varchar char转换_关于char 类型转 varchar类型的问题
  2. 展讯平台-LCD驱动
  3. JAVA线程间通信的几种方式
  4. win7信息服务器iis管理器,Win7系统Internet信息服务(IIS)管理器在哪里打开
  5. 自然语言处理:基于预训练模型的方法(一)
  6. gor工具在测试和压测场景的应用
  7. 自然语言处理 特征提取
  8. vod电影资源机器人 2010元旦第二版
  9. Sun Solaris 用户手册
  10. 稳定状态模型 (一): 微分方程稳定性理论简介