首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在.Net中查找Unicode字符名称

在.Net中查找Unicode字符名称
EN

Stack Overflow用户
提问于 2010-01-19 00:54:12
回答 5查看 5K关注 0票数 25

在.Net中有没有办法找出某个字符有什么Unicode名称?

如果没有,有没有可以做到这一点的库?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-12-11 18:39:56

现在比以往任何时候都简单,因为在nuget中有一个名为Unicode Information的包

有了这个,你可以直接调用:

代码语言:javascript
复制
UnicodeInfo.GetName(character)
票数 33
EN

Stack Overflow用户

发布于 2011-04-19 04:17:38

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

首先,从这里下载Unicode数据库:http://www.unicode.org/Public/UNIDATA/UnicodeData.txt

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

代码语言:javascript
复制
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文件是UTF8编码的,并且每个Unicode码点由一行信息组成。每行包含一个以分号分隔的字段列表,其中第一个字段是十六进制的Unicode代码点(没有前缀),第二个字段是字符名称。有关该文件和每行包含的其他字段的信息可在此处找到:有关UCD格式的信息可在此处找到:http://www.unicode.org/reports/tr44/#Format_Conventions

使用上面的代码构建字符到字符名称的映射后,只需使用如下代码从映射中检索它们:

代码语言:javascript
复制
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字符实际上并不代表一个真正的“字符”(也称为代码点),而是一个Unicode UTF-16代码单元,因为有些“字符”实际上需要两个代码单元。这样的一对代码单元称为高和低代理。大于0xFFFF (16位字符可以存储的最大值)的值超出了基本多语言平面(BMP),并且根据UTF-16编码需要两个char进行编码。作为代理对的一部分的单个代码将在此实现中以"Non Private Use High Surrogate“、"Private Use High Surrogate”和"Low Surrogate“等名称结束。

票数 19
EN

Stack Overflow用户

发布于 2013-12-02 07:58:09

如果使用Process Monitor查看charmap.exe访问的文件,您将看到它打开了一个名为C:\Windows\system32\getuname.dll的文件。该文件在其资源中包含字符名称(实际上,资源本身位于特定于文化的子目录中的.mui文件中)。

因此,您所要做的就是使用LoadString应用编程接口从该文件中获取名称。我写了一个助手类来做这件事:

代码语言:javascript
复制
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
    }
}

你可以这样使用它:

代码语言:javascript
复制
string path = @"C:\Windows\System32\getuname.dll";
using (var reader = new Win32ResourceReader(path))
{
    string name = reader.GetString(0xA9);
    Console.WriteLine(name); // Copyright Sign
}
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2087682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档