一、前言
ICU(International Components for Unicode)是一个跨平台的C++库,用于处理Unicode字符和文本字符串的各种操作。
ICU的主要功能包括:
- 字符串操作:ICU库提供了丰富的字符串操作功能,包括字符串分割、子字符串查找和替换、大小写转换等。
- 格式化和国际化:ICU库使得格式化和解析具有国际化能力的日期、货币、数字和时区等信息变得非常容易。
- 排序和比较:ICU库提供了丰富的字符和字符串排序和比较功能,支持多语言和多种排序规则。
- 正则表达式:ICU库还提供了正则表达式功能,可以进行Unicode字符集的正则匹配和替换。
- 文本转换:ICU库提供了多种字符集和文本格式的转换功能,如Unicode、UTF-8、UTF-16等编码格式之间的转换。
二、安装
最简单的方式就是使用vcpkg包管理,使用方法请参考这篇文章:开源库使用
然后使用命令直接安装即可:
.\vcpkg.exe install icu:x64-windows
或者:
.\vcpkg.exe install icu
或者你也可以去github自己下载:unicode-org/icu
然后选择自己合适的版本进行下载:
下载解压后,就会有下面两个头文件夹与库文件夹:
复制到你的项目中,包含它,链接静态库,这些基本操作就不再赘述了。
推荐使用第一种方法,简单省事。
三、编码转换
想要在C++中操作utf-8编码是一件非常麻烦的事情,但现在大部分应用程序、包括网站都使用的utf-8编码,所以有时候想要处理这些数据就会比较麻烦。
比如我们电脑一般使用的都是GBK编码,而C++默认使用本地编码,也就是GBK编码,也就导致了当你用C++处理UTF-8编码的文本时经常出现乱码的情况。
这个时候我们就需要将其转换为本地GBK编码,再进行操作,也就是编码转换
下面转换操作只用到了一个头文件:
#include <unicode/ucnv.h>
函数只用到了一个:
ucnv_convert
:编码转换
ucnv_convert
函数的参数比较多:
- 第一个参数:你想要转换为的目标编码
- 第二个参数:源字符串编码
- 第三个参数:存放转换结果的缓存区
- 第四个参数:缓存区大小
- 第五个参数:源字符串
- 第六个参数:源字符串的大小
- 第七个参数:返回的错误信息
1.gbk 转 utf-8
std::string gbk_to_utf8(const std::string&gbk) {
UErrorCode error = U_ZERO_ERROR;
std::string u8str((gbk.size()+1) * 2, '\0'); //预留足够大的空间
ucnv_convert("UTF-8", "GBK", (char*)u8str.c_str(), (gbk.size() + 1) * 2, gbk.c_str(), gbk.size(), &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return u8str;
}
2.utf-8 转 gbk
std::string utf8_to_gbk(const std::string& utf8) {
UErrorCode error = U_ZERO_ERROR;
std::string gbkstr((utf8.size() + 1) * 3, '\0'); //预留足够大的空间
ucnv_convert("GBK", "UTF-8", (char*)gbkstr.c_str(), (utf8.size() + 1) * 3, utf8.c_str(), utf8.size(), &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return gbkstr;
}
3.gbk 转 utf-16(宽字符)
std::wstring gbk_to_utf16(const std::string& gbk) {
UErrorCode error = U_ZERO_ERROR;
std::wstring wstr((gbk.size() + 1) * 2, '\0'); //预留足够大的空间
ucnv_convert("UTF-16", "GBK", (char*)wstr.c_str(), (wstr.size() + 1) * 2, gbk.c_str(), gbk.size(), &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return wstr;
}
4.utf16 转 gbk
std::string utf16_to_gbk(const std::wstring& utf16) {
UErrorCode error = U_ZERO_ERROR;
std::string gbkstr((utf16.size() + 1) * 2, '\0'); //预留足够大的空间
ucnv_convert("GBK", "UTF-16", (char*)gbkstr.c_str(), (gbkstr.size() + 1) * 2, (char*)utf16.c_str(), utf16.size()*2, &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return gbkstr;
}
5.utf-8 转 utf16
std::wstring utf8_to_utf16(const std::string& utf8) {
UErrorCode error = U_ZERO_ERROR;
std::wstring wstr(utf8.size()+1, '\0'); //预留足够大的空间
ucnv_convert("UTF-16", "UTF-8", (char*)wstr.c_str(), (wstr.size()+1)*2, utf8.c_str(), utf8.size(), &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return wstr;
}
6.utf-16 转 utf-8
std::string utf16_to_utf8(const std::wstring& utf16) {
UErrorCode error = U_ZERO_ERROR;
std::string gbkstr((utf16.size() + 1) * 3, '\0'); //预留足够大的空间
ucnv_convert("UTF-8", "UTF-16", (char*)gbkstr.c_str(), (gbkstr.size() + 1) * 3, (char*)utf16.c_str(), utf16.size() * 2, &error);
if (U_FAILURE(error)) {
throw "Failed to convert string";
}
return gbkstr;
}
7.测试
int main() {
std::string u8str = gbk_to_utf8("kucoding.com 余识\n");
std::wstring wstr = utf8_to_utf16(u8str);
u8str=utf16_to_utf8(wstr);
std::string str = utf8_to_gbk(u8str);
wstr = gbk_to_utf16(str);
str=utf16_to_gbk(wstr);
std::cout << str;
}
因为cout只能输出本地字符集,所以上面的代码直接把gbk编码字符串通过6个转换编码函数反复转换后,回到本地gbk编码,并进行输出。
四、日期与时间
需要头文件:
#include<unicode/datefmt.h>
代码:
UDate now=ucal_getNow();
icu::DateFormat* dfmt=icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull, icu::DateFormat::kFull);
icu::UnicodeString str;
dfmt->format(now, str);
delete dfmt;
通过函数ucal_getNow
获取当前时间,然后再通过一个日期时间格式化实例对这个时间进行格式化