跨平台Unicode字符编码转换,ICU库简单介绍
一、简介
ICU是一套成熟的、广泛使用的C/C++和java库,提供Unicode和全球化支持、可移值、在所有平台上以及在C/C++和Java软件之间为应用程序提供相同的结果。
ICU提供的服务一些亮点:
- Code Page Conversion: Convert text data to or from Unicode and nearly any other character set or encoding.
- Collation:Compare strings according to the conventions and standards of a particular language,region or country.
- Formatting:Format numbers,dates,times and currency amounts according the conventions of chosen locale.
- Regular Expression:ICU's regular expressions fully support Unicode while providing very competitive performance.
- Bidi:support for handling containing a mixture of left or right(English) and right to left(Arbic or Hebrew) data.
- Text Boundaries:Locate the positions of word,sentences,paragraphs within a range of text, or identify locations that would be suitable for line wrapping when displying the text.
- and so on.
ICU库有很多功能,不过这里这关注了Code Page,即将文本数据与Unicode以及其他字符集或编码进行转换,如对其他功能感兴趣,可以观看官网https://icu.unicode.org/。
二、安装ICU4C
本文统一环境:window10 x64,IDE是VS2019。
可以下载编译好的动态库或者源码编译安装。
-
下载编译好的动态库
网址为:https://github.com/unicode-org/icu/releases/tag/release-71-1
选择icu4c-71_1-Win64-MSVC2019.zip以及icu4c-71_1-data-bin-l.zip ,这两个文件,前者是动态库,后者是ICU_DATA,字节序是小端,windows10 x64是小端。
-
源码编译
下载地址为:https://github.com/unicode-org/icu/archive/refs/tags/release-71-1.zip
解压后,进入目录icu4c/source/allinone,使用VS2019打开allione.sh,然后进行编译。
或者,使用命令行进行编译,具体可以参考官方,https://unicode-org.github.io/icu/userguide/icu4c/build.html#running-the-tests-from-the-windows-command-line-cmd。
三、使用示例
#include <cstdlib>
#include <cstdio>
#include <string>
#include <iostream>
#include "unicode/putil.h"
#include "unicode/udata.h"
#include "unicode/ucnv.h"
namespace {
char* g_icu_data_ptr = nullptr;
void free_icu_data_ptr() { delete[] g_icu_data_ptr; std::cout << "free icu data." << std::endl; }
}
bool init_icu()
{
FILE* inf = fopen("D:\\workspace\\KeyWords\\commondata\\icudt71l.dat", "rb");
if (!inf) return false;
std::shared_ptr<FILE> p_inf(inf, fclose);
fseek(inf, 0, SEEK_END);
size_t size = ftell(p_inf.get());
rewind(p_inf.get());
//分配内存,用于存储icu data
char* icu_data_ptr = new char[size];
if (fread(icu_data_ptr, 1, size, inf) != size)
{
delete[] icu_data_ptr;
icu_data_ptr = nullptr;
return false;
}
//main函数退出时调用,用于释放存储icu data的内存,该数据只能在程序结束后释放,否则后续使用icu方法时会出错。
atexit(free_icu_data_ptr);
UErrorCode err = U_ZERO_ERROR;
udata_setCommonData(reinterpret_cast<void*>(icu_data_ptr), &err);
// Never try to load ICU data from files.
udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
return err == U_ZERO_ERROR;
}
int main()
{
//初始化ICU DATA,本列中是必须,否则转换错误。
if(!init_icu()) return -1;
std::string word = "好啊";
UErrorCode status{ U_ZERO_ERROR };
size_t enough_size = 4*word.size();
std::shared_ptr<char> sp_buf(new char[enough_size], [](char* p) {delete[] p; p = nullptr;});
int len = ucnv_convert("UTF8", NULL, sp_buf.get(), enough_size, word.c_str(), word.size(), &status);
if (U_FAILURE(status))
{
return -1;
}
//输出16进制
std::cout << std::hex;
for (int32_t i = 0; i < len; ++i)
{
std::cout << int((uint8_t)sp_buf.get()[i]) << " ";
}
return 0;
}
1 因为是在windows系统下,std::string word = "好啊"; 2 编译器会翻译成gbk编码,即"\xba\xc3\xb0\xa1"。 3 4 main函数中调用ucnv_convert("UTF8",NULL,...)方法,将word转成 5 UTF8编码的字节序。 6 7 最终打印出来的16进制为: 8 e5 a5 bd e5 95 8a 9 刚好是"好啊"的UTF8编码序列。
四、结语
ICU还有很多强大的功能,对Unicode的支持非常全面,这里只是列举了编码转换的方法。

浙公网安备 33010602011771号