Выяснение имени персонажа Unicode в .Net - PullRequest
20 голосов
/ 18 января 2010

Есть ли способ в .Net выяснить, какое имя Unicode имеет определенный символ?

Если нет, есть ли библиотека, которая может это сделать?

Ответы [ 6 ]

23 голосов
/ 11 декабря 2014

Теперь это проще, чем когда-либо, поскольку в nuget есть пакет с именем Unicode Information

С этим вы можете просто позвонить:

UnicodeInfo.GetName(character)
10 голосов
/ 19 апреля 2011

Вот решение, которое вы можете реализовать немедленно, например, копировать / вставить / скомпилировать.

Сначала загрузите базу данных Unicode (UCD) здесь: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt

Затем добавьте этот код в ваш проект, чтобы прочитать UCD, и создайте словарь для поиска имени значения символа .NET:

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 с. Индивидуальные коды, которые являются частью суррогатной пары, будут иметь такие имена, как «Высокий суррогат не частного использования», «Высокий суррогат частного использования» и «Низкий суррогат» в этой реализации.

8 голосов
/ 02 декабря 2013

Если вы используете Process Monitor для просмотра файлов, к которым обращается 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
}
6 голосов
/ 18 января 2010

Это не встроенная функция в .NET. Вы можете узнать из Charmap.exe, он отображает имя кодовой точки в строке состояния. Если вам это нужно в вашей собственной программе, вы можете скомпилировать Unicode Character Database в свое приложение. Остерегайтесь авторских прав.

4 голосов
/ 18 января 2010

Я не думаю, что есть что-то встроенное в .NET, чтобы идентифицировать это ... Но есть База данных символов Unicode .

0 голосов
/ 20 января 2010

Как сказали NoBugz и MichaelBray .net Не предоставляйте никакой встроенной функции для получения Unicode Name символов.

И вы должны использовать из базы данных символов Unicode, которая предоставляет bUnicode.o по номеру http://unicode.org/ucd, сегодня она содержит полную информацию всей информации о кодировщиках Unicode 5.2 (приложение № 44)

Еще одна альтернатива - использовать из Windows Character Map wicth. Доступ к ней можно получить через Пуск \ Программы приложений \ Стандартные \ Системные инструменты \ Карта символов (win + R => charmap)

А также вы можете использовать из Unicode Converter Tools, который является инструментом с открытым исходным кодом на http://unicode.codeplex.com, он также предоставляет пользовательский интерфейс для получения информации, а также его использование из Unicode UCD (приложение № 44), суть этого Программное обеспечение для Вас заключается в том, что Вы можете добавить EnterPriseAppUnit dll этого приложения к своей заявке и использовать его из предоставленного API.

эта сборка содержит некоторый статический метод, который дает Char и возвращаемое имя, HexCode, десятичный код и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...