我们还可以根据程序处理字符串时, 主要还是依赖标准库函数:c语言, glib, wchar等
一,相关概念
可以在google上找一些编码发展历史与一些基本概念,如: ucs-2, usc-4, utf8, utf16…
1.1 unicode与utf8
Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
UNICODE 如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到UTF时并不是直接的对应,而是要过一些算法和规则来转换。UTF-8是Unicode的实现方式之一。
1.2 charset与encoding的区别?
Charset/Encoding(字符集/编码)。Charset很容易和Encoding搞混,也是刚开始接触字符编码问题是最容易被晕掉的概念。字符集的概念,实际上,包含两个方面,一个,是字符的集合,即所谓的Charset,一个是编码方案,也就是所谓的Encoding。所谓字符的集合,意即一个字符集,定义了它所包含的所有符号,这实际上正是字符集名字的真正含义。也就是说,狭义上的字符集,并不包含编码方案,它仅仅是定义了哪些符号属于这个字符集。
3.2看一个字符的unicode或utf8的工具
UltraEdit ->Edit->Hex Edit
3.3 字符
我们常说的字符是一个汉字是一个字符,一个ascii也是一个字符,所以一个字符可能对应多个字节.
二, c语言的字符处理函数能来处理utf8编码的字符吗?
2.1 字节与字符
虽然c语言只提供单字节处理函数, glib提供的utf8处理的API,主要是对处理字符的,如果对于处理字节c的一些常用函数还是可以用的
c的很字符串函数都是locale无关的,它们都是处理以'/0'为结尾的字节串,如:strcpy,strncpy,strcat,strncat,strcmp,strncmp,strdup,strchr,strtok
2.2 C函数strlen()总是返回字符串在内存中占据的字节数。
若strlen()被用于该目的而被调用,不需要进行改动,但如果你要得到字符串的长度,你就能用宽字符处理函数g_utf8_strlen,
如: char * a = “你我” strlen(a) = 5; g_utf8_strlen(a,-1)=2 ;
2.3 用Strncpy,strndup,strncmp..你必须搞清楚你处理的是字节还是字符,如果是字符哪就要用宽字符处理函数如: g_utf8_strncpy, g_utf8_strup, g_utf8_collate
如:oma mms subject不能超过40个ascii 字节,我们只能用strncpy去cut off而不能用g_utf8_strncpy
g_strncpy(tmpSubj, subjectP, MSG_SUBJECT_MAX_LENGTH);
2.4 单个字符的处理,所有涉及单个字符的处理都必要用宽字符处理函数:
如: 取掉string中的空格
static void prv_strip_leading_blanks(const gchar **srcPP)
{
gunichar c;
const gchar *srcP = NULL;
if (srcPP == NULL || *srcPP == NULL) return;
srcP = *srcPP;
c = g_utf8_get_char(srcP);
while (*srcP && g_unichar_isspace(c)) {
srcP = g_utf8_next_char(srcP);
c = g_utf8_get_char(srcP);
}
// chars need to be removed
*srcPP = srcP;
}
2.5 g_strdup_printf(),g_strstrip ..是utf8是安全的
2.6 g_strrevese是不安全的
2.7 strcpy,既可以用于单字节字符集(如ISO 8859-1),也可以用于多字节编码(如UTF-8)的字符集,因为它们完成的任务无需了解一个字符究竟对应几个字节.
2.8 strchr, 完成的任务则依赖于一个 字符编码成一个字节,因此对于UTF-8用处不大(如果在UTF-8字符串中寻找ASCII字符的话,strchr依然能正常工作)
三,monolith的实际应用
个人理解monolith中大部分都是utf8编码的,好像search库是utf16.localemgr中间件是专门处理locale相关的事务的,你可以取出系统中的字符集(charset)与编码方式(encoding)
3.1 charset与encoding的使用
如: Email/Messaging send时,我们要告诉postal当前系统的charset与encoding,这样接受者能准确的显示它们.
/*! @brief Bodypart content type charset. */
#define ALP_POSTAL_PROPERTY_BODYPART_CONTENT_TYPE_CHARSET /
ALP_POSTAL_PROPERTY(ALP_POSTAL_SERVICE_ID_COMMON, ALP_POSTAL_SERVICE_CLASS_ID_BODYPART, ALP_POSTAL_PROPERTY_TYPE_C_STRING, 15)
/*! @brief Bodypart content location native charset encoding. */
#define ALP_POSTAL_PROPERTY_BODYPART_CONTENT_NATIVE_CHARSET /
ALP_POSTAL_PROPERTY(ALP_POSTAL_SERVICE_ID_COMMON, ALP_POSTAL_SERVICE_CLASS_ID_BODYPART, ALP_POSTAL_PROPERTY_TYPE_C_STRING, 23)
/*! @brief Bodypart content transfer encoding. */
#define ALP_POSTAL_PROPERTY_BODYPART_CONTENT_TRANSFER_ENCODING /
ALP_POSTAL_PROPERTY(ALP_POSTAL_SERVICE_ID_COMMON, ALP_POSTAL_SERVICE_CLASS_ID_BODYPART, ALP_POSTAL_PROPERTY_TYPE_C_STRING, 20)
3.2 当前monolith项目中处理多字节应用
主要看你是处理字节还是处理字符?
3.2.1涉及单个字符的处理的,要用宽字节处理函数,用指针取字符时要小心,如果是utf8的一定要用g_utf8_next_char,g_utf8_prev_char等
如1:设置字符串位置
force_edit_set_cursor_position:
/browser/src/alp_browser_page_callback.c: force_edit_set_cursor_position(edit, g_utf8_strlen(in_initString, -1));
如2:去掉字符串中的空格
unified/msg_compose_contact_activity.c/ prv_strip_trailing_blanks
3.2.2明确要限制字符串个数的函数要用宽字节处理函数
如:contact vart的名子就是限制宽字符个数的
其它用到utf8 处理函数的,用单字节处理也是一样用,都是处理/0结束的字符串.如: g_utf8_collate与strcmp效果可能一样吧(个人理解)
3.5 strncpy与乱码的问题
可能会出现乱码,因为utf8 是可变长编码,一个字符可能有三个字节组成,如果是数组定义的字节长度,哪么没办法,只能用strncpy
3.6 用g_utf8_strncpy时一定要问问自己是不是在处理字符个数.
3.6 limited length是字节数还是字符数
这要看具体的应用了要求了,限制字节个数比较明确,但要处理乱码问题;限制字符时字节个数就变的不定了,因为unf8是变长的编码方式.但monolith中约%90都是限制字节个数.
有exchange关联的应用要一致,如:contacts vcard名子是限制字符个数的.相应用这个名子也用一样.