由于近期项目中要用到emoji表情,而android 的是UTF-16的编码,IOS是SBUnicode编码,相关算法转换找了好多资料没有找到,IOS引用了三方类库可以通过Unicode编码来解emoji表情所以参考了下面项目和算法转换了一下。
http://blog.youkuaiyun.com/recall2012/article/details/46989955 android studic环境项目地址
http://www.apkbus.com/forum.php?mod=viewthread&tid=172819 android eclipse环境项目地址
http://hedleyyan.github.io/blog/2015/08/05/mysql5-dot-5-yi-xia-ban-ben-tong-guo-java-zhuan-yi-shi-xian-emoji-cun-qu/
emoji 中的Unicode 编码转换成表情算法是根据这个大神写的算法改编的具体看上面网址
核心代码:
public class EmojiCharacter {
// high offset
public static final int W1 = Integer.valueOf("D7C0",16);
// low offset
public static final int W2 = Integer.valueOf("DC00",16);
public static void main(String[] args) {
// ��的二进制字符串表示//16|2字符串
String doughnutBinary = Integer.toBinaryString(Integer.valueOf("1F604",16));
System.out.println(doughnutBinary);
// 拆成高低 10 位表示
String highSetsBinary = doughnutBinary.substring(0, doughnutBinary.length() - 10);
String lowSetsBinary = doughnutBinary.substring(doughnutBinary.length() - 10, doughnutBinary.length());
System.out.println(highSetsBinary); // 1111100
System.out.println(lowSetsBinary); // 1100000000
// 分别与偏移量相加,得到两个编码值
String highSetsHexFixed = Integer.toHexString(W1 + Integer.valueOf(highSetsBinary, 2));
String lowSetsHexFixed = Integer.toHexString(W2 + Integer.valueOf(lowSetsBinary, 2));
System.out.println(highSetsHexFixed); // d83c
System.out.println(lowSetsHexFixed); // df00//10进制转二进制
// 拼接这两个编码值,还原字符表示
char highChar = (char)Integer.valueOf(highSetsHexFixed, 16).intValue();//16进制转十进制
char lowChar = (char)Integer.valueOf(lowSetsHexFixed, 16).intValue();
System.out.println(highChar); // ?
System.out.println(lowChar); // ?
System.out.println(highChar + "" + lowChar); // ��
}
}
通过注释可以看出来一步步转换的步骤,下面是我自己经过反推出来的根据表情转换成Unicode编码的方法
public static void decompilation{
System.out.println(Integer.toHexString(highChar));
System.out.println(Integer.toHexString(lowChar));
System.out.println((Integer.parseInt(Integer.toHexString(highChar),16)-W1));
System.out.println((Integer.parseInt(Integer.toHexString(lowChar),16)-W2));
System.out.println(Integer.toBinaryString((Integer.parseInt(Integer.toHexString(highChar),16)-W1)) );
System.out.println(Integer.toBinaryString((Integer.parseInt(Integer.toHexString(lowChar),16)-W2)) );
System.out.println(Integer.toBinaryString((Integer.parseInt(Integer.toHexString(highChar),16)-W1)) +Integer.toBinaryString((Integer.parseInt(Integer.toHexString(lowChar),16)-W2)) );
System.out.println(Integer.toHexString(Integer.valueOf(Integer.toBinaryString((Integer.parseInt(Integer.toHexString(highChar),16)-W1)) +Integer.toBinaryString((Integer.parseInt(Integer.toHexString(lowChar),16)-W2)) , 2)));
}
经过这个转换得出的是类似1F604这样的16进制的数,因为IOS那里需要的是0x1f604这种格式的所以要自己添一下0x了,到了这里就可以和IOS同步了接受的时候调用第一个把Unicode转成表情显示,发送的时候调用第二个把表情转成Unicode
经过以上的算法以后我发现新的问题来了就是输入的时候怎么把表情抓出来转换成Unicode发出去呢,还有接受时候怎么转成表情呢?
接受时候转成表情我是用的正则表达式把经过我特殊标记的表情抓出来
举例 :(我把所有表情都用#表情#这样的格式发送的因为表情会自带头0x的所以我抓取的是#0x和后面第一个#之间的值(emoji的Unicode编码的位数不一样所以不能直接确定位数))
public static void extract(){
Pattern pattern=Pattern.compile("#0x.+?#",Pattern.CASE_INSENSITIVE);
Matcher matcher=pattern.matcher("我要#0x1F604##2123123123#0x1F605#");
StringBuffer buffer=new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(buffer, send(matcher.group().replace("#", "")));
}
matcher.appendTail(buffer);
System.out.println(buffer.toString());
}
这样就可以把接受到的表情正确的显示到上面的那个项目中。
至于发送的明天写