iOS的emoji表情在数据库不支持UTF-8格式的处理

来源:互联网 发布:知行论坛北交大登录 编辑:程序博客网 时间:2024/04/30 02:15

前言

最近遇到苹果手机自带的emoji表情的处理问题,由于我们的数据库编码是GBK编码,而苹果的键盘自带的emoji表情,苹果系统的编码格式是UTF8编码,所以在把emoji表情存到GBK编码的数据库的就会出现乱码的现象,这事非常坑爹的事情。但是还有更坑的,由于我们的emoji表情不是有我们客户端来处理的,其实要是我们客户端处理的话很简单,就是把emoji表情处理成相应的唯一字符串,然后存进数据库,字符串GBK编码的数据库肯定可以存。然后我们展示的再处理回来就好,完全我们客户端就可以操作。坑爹的就是,我们传的emoji表情是要给html5去展示,这就存在问题了。


1.如何从一段文字提取emoji表情

下面我给出一个方案,我们知道emoji表情本质就是字符串,是字符串就会有长度,而emoji表情的字符串的长度有2,4,7,3等等,未来随着emoji表情的扩充可能说不定一个emoji表情的长度大于10都有可能,所以我们来遍历一段含有emoji表情的字符串的问题,来检查出有没有emoji表情是很不理想的选择,虽然可能for循环遍历也可能弄出来,但这可能需要花费大量的时间和精力去完成,不过所幸的是,苹果给我们用了一个好的遍历的方法

检测表情的输入- (NSString *)stringContainsEmoji:(NSString *)string{    __block BOOL returnValue = NO;    __block NSString *tempStr = @"";    [string enumerateSubstringsInRange:NSMakeRange(0, [string length])                               options:NSStringEnumerationByComposedCharacterSequences                            usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {                                NSString *tempEmoji = @"";                                const unichar high = [substring characterAtIndex: 0];                                *** Surrogate pair (U+1D000-1F9FF)***                                if (0xD800 <= high && high <= 0xDBFF) {                                    const unichar low = [substring characterAtIndex: 1];                                    const int codepoint = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;                                    if (0x1D000 <= codepoint && codepoint <= 0x1F9FF){                                        returnValue = YES;                                        tempEmoji = [self getEmojiToShijinZhi:substring];                                    }                                     ***Not surrogate pair (U+2100-27BF)***                                } else {                                    if (0x2100 <= high && high <= 0x27BF){                                        returnValue = YES;                                        tempEmoji = [self getEmojiToShijinZhi:substring];                                    }                                }                                if (returnValue == YES) {                                     tempStr = [tempStr stringByAppendingString:tempEmoji];                                }else{                                     tempStr = [tempStr stringByAppendingString:substring];                                }                                returnValue = NO;                            }];    return tempStr;}

上面的* Surrogate pair (U+1D000-1F9FF)*Not surrogate pair (U+2100-27BF)应该是说明emoji表情的uinicode编码范围。

我是参考这个简书作者: [iOS]检测字符串中是否包含emoji表情


2.emoji表情转化成实体字符

实体字符就是emoji表情可以不用做任何处理就可以显示出来是不是很方便,但是它有个很大毛病,不是所有的表情都支持的,因为的苹果自带的emoji表情一直在扩充,但是对应的实体字符不一定跟上脚步,所以emoji表情也是转化成实体字符也是支持部分。

我也是参考一位楼主的文章: 移动前端手机输入法自带emoji表情字符处理

上面的链接说明的很清楚,但是没有说明怎么把emoji表情转化成uinicode编码格式的字符串,uinicode字符串编码再去取十进制的字符,再然后前面加 &# 就可以了,但是我要说是转化成uinicode编码,我在网上查看到这个

- (NSString *)getEmojiToShijinZhi:(NSString *)text{    NSString *hexstr = @"";    for (int i = 0; i < [text length] / 2 && ([text length] % 2 == 0) ; i++)    {        // three bytes        if (([text characterAtIndex:i*2] & 0xFF00) == 0 ) {            hexstr = [hexstr stringByAppendingFormat:@"%1X%1X",[text characterAtIndex:i*2],[text characterAtIndex:i*2+1]];        }else{// four bytes            hexstr = [hexstr stringByAppendingFormat:@"%1X",MULITTHREEBYTEUTF16TOUNICODE([text characterAtIndex:i*2],[text characterAtIndex:i*2+1])];        }    }    LYNSLog(@"(unicode) [%@]",hexstr);    if (![hexstr isEqualToString:@""]) {        NSString * temp10 = [NSString stringWithFormat:@"%lu",strtoul([hexstr UTF8String],0,16)];        LYNSLog(@"心跳数字 10进制 %@",temp10);        //转成数字        int cycleNumber = [temp10 intValue];        LYNSLog(@"心跳数字 :%d",cycleNumber);        return [NSString stringWithFormat:@"&#%d",cycleNumber];    }    return hexstr;}

但是这个有个很大的问题是emoji表情的字符串长度是奇数的话就没法转码,我也不知道是那个楼主的特意写的呢,还是其他的原因,
其实最主要就是

hexstr = [hexstr stringByAppendingFormat:@”%1X%1X”,[text characterAtIndex:i*2],[text characterAtIndex:i*2+1]];

这个%1X就是打印十六进制的,而uinicode就是十六进制的,所以老铁没毛病呀,哈哈,Unicode百度百科 这里就是原因。
所以打印十六进制前面加个U+就是uinicode的表示方法


3.总结

其实他的这个方案也不是解决所有的emoji表情转成实体字符都能显示,只有最基本常用的几个表情才能利用实体字符显示出来,如果谁有更好的方法请告之一下,毕竟分享是一个很有趣的事情,大家共同进步,探讨,才能接触更多的东西,学习了解更多的东西呀

原创粉丝点击