代码之家  ›  专栏  ›  技术社区  ›  svick Raja Nadar

在.NET中查找Unicode字符名

  •  17
  • svick Raja Nadar  · 技术社区  · 15 年前

    有没有办法在.NET中找出特定字符的Unicode名称?

    如果没有,有没有图书馆可以做到这一点?

    7 回复  |  直到 10 年前
        1
  •  21
  •   Rik Hemsley    10 年前

    这比以往任何时候都容易,因为Nuget中有一个名为 Unicode Information

    有了这个,你可以打电话给:

    UnicodeInfo.GetName(character)
    
        2
  •  9
  •   dlras2    10 年前

    这里有一个可以立即实现的解决方案,比如复制/粘贴/编译。

    首先,在此处下载Unicode数据库(UCD): http://www.unicode.org/Public/UNIDATA/UnicodeData.txt

    接下来,将此代码添加到项目中以读取UCD,并创建一个字典以查找.NET char值的名称:

    string[] unicodedata = File.ReadAllLines( "UnicodeData.txt", Encoding.UTF8 );
    Dictionary<char,string> charname_map = new Dictionary<char,string>( 65536 );
    for (int i = 0; i < unicodedata.Length; i++)
    {
        string[] fields = unicodedata[i].Split( ';' );
        int char_code = int.Parse( fields[0], NumberStyles.HexNumber );
        string char_name = fields[1];
        if (char_code >= 0 && char_code <= 0xFFFF) //UTF-16 BMP code points only
        {
            bool is_range = char_name.EndsWith( ", First>" );
            if (is_range) //add all characters within a specified range
            {
                char_name = char_name.Replace( ", First", String.Empty ); //remove range indicator from name
                fields = unicodedata[++i].Split( ';' );
                int end_char_code = int.Parse( fields[0], NumberStyles.HexNumber );
                if (!fields[1].EndsWith( ", Last>" ))
                    throw new Exception( "Expected end-of-range indicator." );
                for (int code_in_range = char_code; code_in_range <= end_char_code; code_in_range++)
                    charname_map.Add( (char)code_in_range, char_name );
            }
            else
                charname_map.Add( (char)char_code, char_name );
        }
    }
    

    unicodedata.txt文件是UTF-8编码的,由每个unicode码位的一行信息组成。每行包含一个以分号分隔的字段列表,其中第一个字段是十六进制(无前缀)的Unicode码位,第二个字段是字符名。有关文件和每行包含的其他字段的信息可以在这里找到:有关UCD格式的信息可以在这里找到: http://www.unicode.org/reports/tr44/#Format_Conventions

    一旦使用上述代码构建字符到字符名的映射,您只需从映射中检索它们,如下所示:

    char c = 'Â';
    string character_name;
    if (!charname_map.TryGetValue( c, out character_name ))
        character_name = "<Character Name Missing>"; //character not found in map
    //character_name should now contain "LATIN CAPITAL LETTER A WITH CIRCUMFLEX";
    

    我建议在应用程序资源中嵌入unicodedata.txt文件,并将此代码包装到一个类中,该类在静态初始值设定项中加载并解析文件一次。为了提高代码的可读性,可以在类“char”类中实现一个扩展方法,如“getunicodename”。我特意将值限制在0到0xffff之间,因为这是.NET UTF-16字符所能容纳的。.NET char实际上并不代表一个真正的“字符”(也称为代码点),而是一个Unicode UTF-16代码单元,因为有些“字符”实际上需要两个代码单元。这样的一对代码单元称为高代理和低代理。大于0xffff(16位字符可以存储的最大值)的值在基本多语言平面(BMP)之外,根据UTF-16编码,需要两个 char S编码。作为代理对的一部分的单个代码将以“非私有使用高代理”、“私有使用高代理”和“低代理”这样的名称结束。

        3
  •  8
  •   Thomas Levesque    11 年前

    如果使用进程监视器查看 charmap.exe ,您将看到它打开一个名为 C:\Windows\system32\getuname.dll . 此文件包含其资源中的字符名(实际上资源本身位于区域性特定子目录中的.mui文件中)。

    因此,您所要做的就是使用 LoadString 应用程序编程接口。我写了一个助手类来完成它:

    public class Win32ResourceReader : IDisposable
    {
        private IntPtr _hModule;
    
        public Win32ResourceReader(string filename)
        {
            _hModule = LoadLibraryEx(filename, IntPtr.Zero, LoadLibraryFlags.AsDataFile | LoadLibraryFlags.AsImageResource);
            if (_hModule == IntPtr.Zero)
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    
        public string GetString(uint id)
        {
            var buffer = new StringBuilder(1024);
            LoadString(_hModule, id, buffer, buffer.Capacity);
            if (Marshal.GetLastWin32Error() != 0)
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            return buffer.ToString();
        }
    
        ~Win32ResourceReader()
        {
            Dispose(false);
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        public void Dispose(bool disposing)
        {
            if (_hModule != IntPtr.Zero)
                FreeLibrary(_hModule);
            _hModule = IntPtr.Zero;
        }
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool FreeLibrary(IntPtr hModule);
    
        [Flags]
        enum LoadLibraryFlags : uint
        {
            AsDataFile = 0x00000002,
            AsImageResource = 0x00000020
        }
    }
    

    您可以这样使用它:

    string path = @"C:\Windows\System32\getuname.dll";
    using (var reader = new Win32ResourceReader(path))
    {
        string name = reader.GetString(0xA9);
        Console.WriteLine(name); // Copyright Sign
    }
    
        4
  •  6
  •   Hans Passant    15 年前

    它不是.NET中的内置功能。您可以从charmap.exe中找到,它在状态栏中显示代码点名称。如果您在自己的程序中需要它,可以编译 Unicode Character Database 进入你的应用程序。当心版权。

        5
  •  4
  •   svick Raja Nadar    13 年前

    我认为.NET中没有内置的东西来识别这个…但是有一个 Unicode character database .

        6
  •  0
  •   Nasser Hadjloo    15 年前

    正如Nobugz和Michaelbray所说,.net不提供任何内置功能来获取字符的Unicode名称。

    必须使用Unicode字符数据库,该数据库在 http://unicode.org/ucd 今天,它包含所有Unicode 5.2字符信息的完整信息(附件44)

    另一种选择是使用Windows字符映射,您可以通过开始\应用程序\附件\系统工具\字符映射(win+r=>charmap)访问它。

    也可以使用Unicode转换器工具,该工具是位于 http://unicode.codeplex.com 它还提供了一个用于获取信息的用户界面,以及它在Unicode UCD(附录44)中的使用。该软件的主要特点是您可以添加 企业应用程序 此应用程序的DLL到您的链接,并从提供的API使用。

    此程序集包含一个静态方法,该方法提供一个字符和返回名、十六进制代码、十进制代码等

        7
  •  -4
  •   David    15 年前

    我想你在找 Encoding.Unicode 对象

    推荐文章