天天看点

unicode中含有双码元字符串的截取

在汉字中,某部分字占了双位,即unicode中占了两个码元(code unit),这种字在输出它的长度时,都是为2,因为在csdn里这种字一旦出现,后面的文章自动截断,所以没办法写明,但这些字可以在下面网站中复制

http://www.scarfboy.com/coding/unicode-tool?s=U%2b279FF

大家可以看到比较多,而这时如果我们对其字符进行substring的话,会弹出:无法将位于索引 0处的 Unicode 字符 \uD85E 转换为指定的代码页

这个问题因为需要处理复杂的繁体才会可能需要,我以前从来没有碰到过,论坛上就有人问了这个问题,百度上找不到,于是自己研究了一下:
           
Char[] cc = "从上面网站上copy一个字进来".ToCharArray();
            Response.Write(cc.Length);
            Char[] cc1 = "我".ToCharArray();
            Response.Write(cc1.Length + "|" + "从上面网站上copy一个字进来".Length);
            //Label1.Text = "从上面网站上copy一个字进来".Substring(0,1);//出错
           

结果里可以看到,这个字的length竟是2,没研究过组合字的飘过。

直接response.write输出substring截断没有问题,但成了另一个字,label.text加载则直接报错,但这个字确实是存在的,我们要怎么进行截断呢,研究了下,可以用下面的方法stringinfo.LengthInTextElements。
           
public static string Substring(int subLen, string Words)
        {
            string temp = string.Empty;
            StringInfo si = new StringInfo(Words);
            int max = si.LengthInTextElements;
            if (si.LengthInTextElements >= subLen)
            {
                string returnstr = string.Empty;
                Char[] cc = Words.ToCharArray();
                max = subLen;
                for (int i = 0; i < max; i++)
                {
                    if ((i + 1) < cc.Length)
                    {

                        StringInfo si2 = new StringInfo(cc[i].ToString() + cc[i + 1].ToString());
                        if (si2.LengthInTextElements == 1)
                        {
                            i++;
                            max++;
                            temp += si2.String.ToString();
                        }
                        else
                        {
                            temp += cc[i].ToString();
                        }
                    }
                    else
                    {
                        temp += cc[i].ToString();
                    }
                }
                
            }
            else
                return Words;
            return temp;
        }