在C#

时间:2019-01-07 18:11:22

标签: c# unicode

我正在设计一个API,其中API用户需要以Unicode格式返回阿拉伯文本,为此,我尝试了以下操作:

public static class StringExtensions
{
    public static string ToUnicodeString(this string str)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var c in str)
        {
            sb.Append("\\u" + ((int)c).ToString("X4"));
        }
        return sb.ToString();
    }
}

上述代码的问题是,无论其在单词中的位置如何,它都会返回字母的unicode。

示例:让我们假设我们有以下单词:

“سمير”,由以下内容组成:

'س'的写法类似于'سـ',因为它是单词中的第一个字母。

'م'的写法类似于'ـمـ',因为它位于单词的中间。

'ي'的写法类似于'ـيـ',因为它位于单词的中间。

'ر'的写法类似于'lastر',因为它是单词的最后一个字母。

上面的代码返回Unicode的{'س','م','ي','ر'},即:

  

\ u0633 \ u0645 \ u064A \ u0631

代替了

的{'سـ','ـمـ','ـيـ','ـر'}
  

\ uFEB3 \ uFEE4 \ uFEF4 \ uFEAE

关于如何更新代码以获取正确的Unicode的任何想法?

有用的link

2 个答案:

答案 0 :(得分:3)

字符串只是Unicode代码点的序列;它不知道阿拉伯语的规则。您可以准确地取出放入的数据;如果要输出不同的数据,请输入不同的数据!

尝试一下:

Console.WriteLine("\u0633\u0645\u064A\u0631");
Console.WriteLine("\u0633\u0645\u064A\u0631".ToUnicodeString());
Console.WriteLine("\uFEB3\uFEE4\uFEF4\uFEAE");
Console.WriteLine("\uFEB3\uFEE4\uFEF4\uFEAE".ToUnicodeString());

如预期的那样输出

سمير
\u0633\u0645\u064A\u0631
ﺳﻤﻴﺮ
\uFEB3\uFEE4\uFEF4\uFEAE

这两个Unicode代码点序列在浏览器中呈现相同的内容,但它们是不同的序列。如果要写出第二个序列,则不要通过第一个序列。

答案 1 :(得分:0)

基于Eric的回答,我知道如何解决问题,因此我在Github上创建了一个解决方案。

您将找到一个可在Windows上运行的简单工具,如果要在项目中使用代码,则只需复制粘贴UnicodesTable.csUnshaper.cs

基本上,每个阿拉伯字母都需要一个Unicode表,然后可以使用以下扩展方法。

public static string GetUnShapedUnicode(this string original)
    {
        original = Regex.Unescape(original.Trim());
        var words = original.Split(' ');
        StringBuilder builder = new StringBuilder();
        var unicodesTable = UnicodesTable.GetArabicGliphes();
        foreach (var word in words)
        {
            string previous = null;
            for (int i = 0; i < word.Length; i++)
            {
                string shapedUnicode = @"\u" + ((int)word[i]).ToString("X4");
                if (!unicodesTable.ContainsKey(shapedUnicode))
                {
                    builder.Append(shapedUnicode);
                    previous = null;
                    continue;
                }
                else
                {
                    if (i == 0 || previous == null)
                    {
                        builder.Append(unicodesTable[shapedUnicode][1]);
                    }
                    else
                    {
                        if (i == word.Length - 1)
                        {
                            if (!string.IsNullOrEmpty(previous) && unicodesTable[previous][4] == "2")
                            {
                                builder.Append(unicodesTable[shapedUnicode][0]);
                            }
                            else
                                builder.Append(unicodesTable[shapedUnicode][3]);
                        }
                        else
                        {
                            bool previouChar = unicodesTable[previous][4] == "2";
                            if (previouChar)
                                builder.Append(unicodesTable[shapedUnicode][1]);
                            else
                                builder.Append(unicodesTable[shapedUnicode][2]);
                        }
                    }
                }

                previous = shapedUnicode;
            }
            if (words.ToList().IndexOf(word) != words.Length - 1)
                builder.Append(@"\u" + ((int)' ').ToString("X4"));
        }

        return builder.ToString();
    }