2010-01-18 104 views

回答

20

這是比以往更容易了,因爲有一個在的NuGet包名爲Unicode Information

有了這個,您可以撥打電話:

UnicodeInfo.GetName(character) 
+1

太棒了。這是正確的答案!需要更多upvotes – McKay 2015-10-29 14:50:26

-4

我認爲你正在尋找Encoding.Unicode對象

+0

該班級將不會提供OP正在查找的數據... – 2010-01-18 17:06:14

6

它不是.NET中的內置功能。您可以從Charmap.exe中找到,它會在狀態欄中顯示代碼點名稱。如果你需要在自己的程序中,你可以編譯Unicode Character Database到你的應用程序。謹防版權。

0

正如NoBugz和MichaelBray所說.net不提供任何內置功能來獲取Unicode字符的名稱。

,你必須從Unicode字符數據庫,在今天http://unicode.org/ucd提供bUnicode.o它包含的所有Unicode 5.2 charcaters信息的完整信息(附件#44)使用

另一種方法是從Windows字符映射表wicth用途你可以通過開始\應用程序\附件\系統工具\字符映射(win + R => charmap)來訪問它

也可以使用Unicode轉換工具這是一個開源工具,在http://unicode.codeplex.com它也提供用於獲取信息的用戶界面以及從Unicode UCD使用(附件#44)這個軟件的基調爲你的是你可以加EnterPriseAppUnit這個應用程序的dll從您提供的API通用和使用。

大會containsome靜態方法,給出了一個字符,並返回名稱,十六進制編碼,十進制碼和等

9

這裏有一個解決方案,您可以立即執行,如複製/粘貼/編譯。

首先,下載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文件,和包裝這些代碼放到一個類,其負載和靜態初始化一次解析文件。爲了使代碼更具可讀性,您可以在類「charUnicodeName」的類「char」類中實現擴展方法。我故意將值限制在0到0xFFFF範圍內,因爲這是一個.NET UTF-16 char可以容納的。 。NET字符實際上並不代表真正的「字符」(也稱爲代碼點),而是一個Unicode UTF-16代碼單元,因爲一些「字符」實際上需要兩個代碼單元。這樣的一對代碼單元被稱爲高代和低代理。大於0xFFFF的值(16位char可以存儲的最大值)超出了基本多語言平面(BMP),並且根據UTF-16編碼需要兩個編碼。作爲代理對的一部分的單個代碼將最終得到名稱爲「非私用高代理」,「私用高代理」和「低代理」。

7

如果使用進程監視器查看由charmap.exe訪問的文件,您會看到它打開一個名爲C:\Windows\system32\getuname.dll的文件。此文件在其資源中包含字符名稱(實際上,資源本身位於文化特定的子目錄中的.mui文件中)。

因此,您只需使用LoadString API從此文件中獲取名稱即可。我寫了一個輔助類來做到這一點:

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 
} 
+0

lifetim節省。 – Jichao 2015-07-07 08:32:03

+0

非常好(至少如果你碰巧有Windows在手)。另請參閱http://www.pinvoke.net/default.aspx/getuname/GetUName.html – unbob 2016-02-26 16:41:06

+0

其優點是它內置於Windows(甚至是XP)。缺點是字符串是本地化的並且包含一個字符串中的所有信息。不是分別給我提供「姓名」和「類別」信息,而是將所有信息都返回給一個字符串。例如在西班牙語的Windows上:「Letra latinamayúsculaG con gancho」。爲此,我更喜歡Rik Hemsley接受的答案。他的圖書館提供了更多的信息。 – Elmue 2017-10-06 19:18:34