C# .net Emoji字体 Unicode编码转UTF16内码字符串输出

本文介绍了一种将特定格式的Emoji编码转换为能在Windows 8.1、iOS及Android上直接显示的方法。通过代码实现,使得包含特殊Emoji编码的文本可以正确地在不同平台上展示。

Phone / iPad的,Android的4.4+和Windows 8.1+是原生支持Emoji繪文字符號。這裡有五個大類845繪文字符號。無需安裝任何應用程序或軟件, win7 或者xp 安装 Segoe UI Emoji 字体以后也可以支持
参考 http://tw.piliapp.com/emoji/list
如果想要把笑脸
[e]1f604[/e]
输出
换成Emojs字体的字符串需要用到下面的代码.
搞了1天,终于搞定了.编码转来转去..好复杂。

使用方法 如下.

 string a = @" 中间有中文 [e]1f604[/e]也可以[e]1f612[/e][e]1f60c[/e][e]1f60c[/e][e]1f60d[/e][e]1f616[/e][e]1f632[/e][e]1f632[/e][e]1f632[/e][e]1f632[/e][e]1f616[/e][e]1f632[/e] 
";

string b = GetEmoji(a);//这里b输出的就是笑脸了.

下面是具体的代码


        /// <summary>
        /// 把 Emoji编码 [e]1f1e6-1f1fa[/e]
        ///     [e]1f1e6[/e]
        ///     [e]1f1fa[/e]
        ///     [e]1f1e6[/e]
        ///     [e]1f1f9[/e] 换成对应的字符串,此字符串能被window8.1,ios,andriod 直接显示.
        ///     
        /// 如果在网页中显示,需要设置字体为 'Segoe UI Emoji' 如下.当然客户机还必须得有这个字体.
        /// 
        ///     <span style="font-family:'Segoe UI Emoji';"></span>
        ///     
        /// </summary>
        /// <param name="paramContent"></param>
        /// <returns></returns>
        public string GetEmoji(string paramContent)
        {
            string paramContentR = paramContent.Replace("[e]", "\\u").Replace("[/e]", "");


            var unicodehex = new char[6] { '0', '0', '0', '0', '0', '0' };

            StringBuilder newString = new StringBuilder(2000);
            StringBuilder tempEmojiSB = new StringBuilder(20); 
            StringBuilder tmps = new StringBuilder(5);

            int ln = paramContent.Length; 
            for (int index = 0; index < ln; index++)
            {
                    int i = index; //把指针给一个临时变量,方便出错时,现场恢复.
                    try
                    {

                            if (paramContent[i] == '[')
                            { 
                                //预测
                                if (paramContent[i + 1] == 'e')
                                {
                                    if (paramContent[i + 2] == ']') //[e]的后面4位是 unicode 的16进制数值.
                                    {
                                        i = i + 3; //前进3位 

                                        i = ChangUnicodeToUTF16(paramContent, tempEmojiSB, tmps, i);  

                                        if (paramContent[i] == '-')//向前探测1位 看看是否双字符 形如1f1e7-1f1ea 
                                        {
                                            i++;
                                            i = ChangUnicodeToUTF16(paramContent, tempEmojiSB, tmps, i);

                                        };

                                        if (paramContent[i] == '[')
                                        {
                                            if (paramContent[i + 1] == '/')
                                            {
                                                if (paramContent[i + 2] == 'e')
                                                {
                                                    if (paramContent[i + 3] == ']')
                                                    {
                                                        i = i + 3; //再前进4位

                                                        index = i;                             //识别转换成功
                                                        newString.Append(tempEmojiSB.ToString());   //识别转换成功
                                                        tempEmojiSB.Clear();
                                                        continue;
                                                    }
                                                }
                                            }
                                        }

                                    }
                                }
                            }

                            index = i;

                    }catch(Exception ex ){
                        //解析失败仍然继续吃.
                    }
                    newString.Append(paramContent[index]);    

            }
            return newString.ToString();
        }

        ///// <summary>
        ///// 检测字符是否是合法的Emoji字符串
        ///// </summary>
        ///// <param name="paramContent"></param>
        ///// <param name="i"></param>
        ///// <returns></returns>
        //private bool checkNextEmoji(string paramContent, int i)
        //{
        //    //状态说明,
        //    //[ e ] * [ \ e ]
        //    //0 1 2 3 4 5 6 7
        //    int state = 0;
        //    int lencount = 0;
        //    while (i < paramContent.Length)
        //    {
        //        switch (state)
        //        {
        //            case 0:
        //                if (paramContent[i] == '[') state = 1; else return false;
        //                    break; 
        //            case 1:
        //                    if (paramContent[i] == 'e') state = 2; else return false;
        //                    break; 
        //            case 2:
        //                    if (paramContent[i] == ']') state = 3; else return false;
        //                    break; 
        //            case 3:
        //                    if (paramContent[i] == '[')  state = 4; 
        //                    else
        //                    { //这里识别 * 任何符号.如果超出了规定的长度,那么视为未匹配.防止陷入无限死循环
        //                        if (lencount < 20) {
        //                            lencount++;
        //                        }else {
        //                            return false;
        //                        }
        //                        state = 3;
        //                    }
        //                    break; 
        //            case 4:
        //                    if (paramContent[i] == '/') state = 5; else return false;
        //                    break;
        //            case 5:
        //                    if (paramContent[i] == 'e') state = 6; else return false;
        //                     break;
        //            case 6:
        //                    if (paramContent[i] == ']')
        //                        state = 7;
        //                    else return false;
        //                        break; 
        //            case 7: 
        //                    return true; 
        //            default:
        //                return false;
        //        }

        //        i++;
        //    }

        //    return state == 7;
        //}


        public int ChangUnicodeToUTF16(string paramContent, StringBuilder tempSB, StringBuilder tmps, int i)
        { 
            for (int maxln = 0; maxln < 20; maxln++)
            {
                if (paramContent[i] != '-' && paramContent[i] != '[')
                {  //向前探测1位
                    tmps.Append(paramContent[i]);
                    i++;
                }
                else
                {
                    break;
                }
            } 


            tempSB.Append(EmojiCodeToUTF16String(tmps.ToString()));  

            tmps.Clear();
            return i;
        }

        /// <summary>
        /// EmoJi U+字符串对应的 int 值 转换成UTF16字符编码的值
        /// </summary>
        /// <param name="V">EmojiU+1F604 转成计算机整形以后的值V=0x1F604 </param>
        /// <param name="LowHeight">低字节在前的顺序.(默认)</param>
        /// <remarks>
        ///参考  
        ///http://blog.youkuaiyun.com/fengsh998/article/details/8668002
        ///http://punchdrunker.github.io/iOSEmoji/table_html/index.html
        /// V  = 0x64321
        /// Vx = V - 0x10000
        ///    = 0x54321
        ///    = 0101 0100 0011 0010 0001
        ///
        /// Vh = 01 0101 0000 // Vx 的高位部份的 10 bits
        /// Vl = 11 0010 0001 // Vx 的低位部份的 10 bits
        /// wh = 0xD800 //結果的前16位元初始值
        /// wl = 0xDC00 //結果的後16位元初始值
        ///
        /// wh = wh | Vh
        ///    = 1101 1000 0000 0000
        ///    |        01 0101 0000
        ///    = 1101 1001 0101 0000
        ///    = 0xD950
        ///
        /// wl = wl | Vl
        ///    = 1101 1100 0000 0000
        ///    |        11 0010 0001
        ///    = 1101 1111 0010 0001
        ///    = 0xDF21
        /// </remarks>
        /// <returns>EMOJI字符对应的UTF16编码16进制整形表示</returns>
        public Int32 EmojiToUTF16(Int32 V, bool LowHeight = true)
        {

            Int32 Vx = V - 0x10000;

            Int32 Vh = Vx >> 10;//取高10位部分
            Int32 Vl = Vx & 0x3ff; //取低10位部分
            //Response.Write("Vh:"); Response.Write(Convert.ToString(Vh, 2)); Response.Write("<br/>"); //2进制显示
            //Response.Write("Vl:"); Response.Write(Convert.ToString(Vl, 2)); Response.Write("<br/>"); //2进制显示

            Int32 wh = 0xD800; //結果的前16位元初始值,这个地方应该是根据Unicode的编码规则总结出来的数值.
            Int32 wl = 0xDC00; //結果的後16位元初始值,这个地方应该是根据Unicode的编码规则总结出来的数值.
            wh = wh | Vh;
            wl = wl | Vl;
            //Response.Write("wh:"); Response.Write(Convert.ToString(wh, 2)); Response.Write("<br/>");//2进制显示
            //Response.Write("wl:"); Response.Write(Convert.ToString(wl, 2)); Response.Write("<br/>");//2进制显示
            if (LowHeight)
            {
                return wl << 16 | wh;   //低位左移16位以后再把高位合并起来 得到的结果是UTF16的编码值   //适合低位在前的操作系统 
            }
            else
            {
                return wh << 16 | wl; //高位左移16位以后再把低位合并起来 得到的结果是UTF16的编码值   //适合高位在前的操作系统
            }


        }

        /// <summary>
        /// 字符串形式的 Emoji 16进制Unicode编码  转换成 UTF16字符串 能够直接输出到客户端
        /// </summary>
        /// <param name="EmojiCode"></param>
        /// <returns></returns>
        public string EmojiCodeToUTF16String(string EmojiCode)
        {
            if (EmojiCode.Length != 4 && EmojiCode.Length != 5 )
            {
                throw new ArgumentException("错误的 EmojiCode 16进制数据长度.一般为4位或5位");
            }
            //1f604
            int EmojiUnicodeHex = int.Parse(EmojiCode, System.Globalization.NumberStyles.HexNumber);

            //1f604对应 utf16 编码的int
            Int32 EmojiUTF16Hex = EmojiToUTF16(EmojiUnicodeHex, true);             //这里字符的低位在前.高位在后.
            //Response.Write(Convert.ToString(lon, 16)); Response.Write("<br/>"); //这里字符的低位在前.高位在后. 
            var emojiBytes = BitConverter.GetBytes(EmojiUTF16Hex);                     //把整型值变成Byte[]形式. Int64的话 丢掉高位的空白0000000   

            return Encoding.Unicode.GetString(emojiBytes);
        }
C#中实现不同字体字符串Unicode码之间的换,主要依赖于.NET框架提供的编码和解码机制。尽管字体本身并不直接影响字符串Unicode表示,但字体决定了字符在屏幕上如何渲染。以下将从两个方面进行说明:**将字符串换为Unicode码**以及**将Unicode码还原为字符串**。 ### 将字符串换为Unicode码 在C#中,可以使用`System.Text.Encoding`类中的方法将字符串换为Unicode编码的字节数组。默认情况下,.NET中的`Encoding.Unicode`指的是UTF-16编码,它使用16位(2字节)来表示字符[^1]。 ```csharp string originalString = "你好,世界"; byte[] unicodeBytes = Encoding.Unicode.GetBytes(originalString); // 输出每个字节的十六进制表示 foreach (byte b in unicodeBytes) { Console.Write(b.ToString("X2") + " "); } ``` 上述代码将输出类似`E4 ½ A0 E5 A5 BD EF BC 8C E4 B8 96 E7 95 8C`的内容,这是原始字符串Unicode(UTF-16编码下的字节表示。 ### 将Unicode码还原为字符串 要将字节数组还原为原始字符串,可以使用`Encoding.Unicode.GetString()`方法: ```csharp byte[] unicodeBytes = new byte[] { 0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD, 0xEF, 0xBC, 0x8C, 0xE4, 0xB8, 0x96, 0xE7, 0x95, 0x8C }; string decodedString = Encoding.Unicode.GetString(unicodeBytes); Console.WriteLine(decodedString); // 输出: 你好,世界 ``` ### 处理不同编码格式 如果需要处理其他编码格式(如UTF-8),可以使用`Encoding.UTF8`代替`Encoding.Unicode`: ```csharp byte[] utf8Bytes = Encoding.UTF8.GetBytes(originalString); string decodedFromUtf8 = Encoding.UTF8.GetString(utf8Bytes); ``` 需要注意的是,UTF-8是一种变长编码,某些字符可能占用1到4个字节,而UTF-16则通常使用2或4个字节[^2]。 ### 字体与字符显示的关系 虽然字体不会影响字符串的内部编码方式,但它决定了字符在界面上的呈现效果。在Windows Forms或WPF应用中,可以通过设置控件的`Font`属性来指定使用的字体: ```csharp label1.Font = new Font("SimSun", 12); // 使用宋体显示文本 label1.Text = "你好,世界"; ``` 若需动态加载字体文件(例如.ttf文件),可使用`PrivateFontCollection`类来注册自定义字体: ```csharp PrivateFontCollection privateFonts = new PrivateFontCollection(); privateFonts.AddFontFile("path/to/customfont.ttf"); Font customFont = new Font(privateFonts.Families[0], 12); label1.Font = customFont; ``` ### 特殊字符处理 对于一些特殊字符或非标准字符集,建议使用`char.ConvertToUtf32()`和`char.ConvertFromUtf32()`方法进行高代理项(surrogate pairs)处理: ```csharp int codePoint = char.ConvertToUtf32("😊", 0); // 获取表情符号Unicode码点 string emoji = char.ConvertFromUtf32(codePoint); // 从码点还原为字符串 ``` 这些方法特别适用于处理超出基本多语言平面(BMP)范围的字符(即码点大于U+FFFF的字符)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值