Подтвердить что ты не робот

Возвращать кодовую точку символов в С#

Как я могу вернуть Unicode Code Point символа? Например, если вход "A", то выход должен быть "U + 0041". В идеале, решение должно позаботиться о суррогатных парах.

С кодовой точкой я имею в виду фактическую кодовую точку в соответствии с Unicode, которая отличается от блок кода (UTF8 имеет 8-битные кодовые единицы, UTF16 имеет 16-битные кодовые единицы, а UTF32 имеет 32-битные кодовые единицы, в последнем случае значение равно кодовой точке, после учета энтузиазма).

4b9b3361

Ответ 1

Легко, поскольку символы в С# на самом деле являются кодовыми точками UTF16:

char x = 'A';
Console.WriteLine("U+{0:x4}", (int)x);

Чтобы адресовать комментарии, A char в С# - это 16-битное число и содержит кодовую точку UTF16. Кодовые точки выше 16 битового пространства не могут быть представлены символом С#. Символы в С# не являются переменной шириной. Строка, однако, может иметь 2 символа, следующие друг за другом, каждый из которых является блоком кода, образуя кодовую точку UTF16. Если у вас есть строковый ввод и символы над 16-битным пространством, вы можете использовать char.IsSurrogatePair и Char.ConvertToUtf32, как это предлагается в другом ответе:

string input = ....
for(int i = 0 ; i < input.Length ; i += Char.IsSurrogatePair(input,i) ? 2 : 1)
{
    int x = Char.ConvertToUtf32(input, i);
    Console.WriteLine("U+{0:X4}", x);
}

Ответ 2

Следующий код записывает кодовые точки ввода string на консоль:

string input = "\uD834\uDD61";

for (var i = 0; i < input.Length; i += char.IsSurrogatePair(input, i) ? 2 : 1)
{
    var codepoint = char.ConvertToUtf32(input, i);

    Console.WriteLine("U+{0:X4}", codepoint);
}

Вывод:

U+1D161

Так как строки в .NET кодируются в кодировке UTF-16, значения char, которые составляют строку, должны быть сначала преобразованы в UTF-32.

Ответ 3

На самом деле есть определенная заслуга в ответе @Yogendra Singh, в настоящее время единственная с отрицательным голосованием. Работа может быть выполнена следующим образом

    public static IEnumerable<int> Utf8ToCodePoints(this string s)
    {
        var utf32Bytes = Encoding.UTF32.GetBytes(s);
        var bytesPerCharInUtf32 = 4;
        Debug.Assert(utf32bytes.Length % bytesPerCharInUtf32 == 0);
        for (int i = 0; i < utf32bytes.Length; i+= bytesPerCharInUtf32)
        {
            yield return BitConverter.ToInt32(utf32bytes, i);
        }
    }

Протестировано с помощью

    var surrogatePairInput = "abc💩";
    Debug.Assert(surrogatePairInput.Length == 5);
    var pointsAsString = string.Join(";" , 
        surrogatePairInput
        .Utf8ToCodePoints()
        .Select(p => $"U+{p:X4}"));
    Debug.Assert(pointsAsString == "U+0061;U+0062;U+0063;U+1F4A9");

Пример имеет значение, потому что куча poo представляется как суррогатная пара.

Ответ 4

С# не может хранить кодовые точки Unicode в char, так как char составляет всего 2 байта, а кодовые номера Unicode обычно превышают эту длину. Решение состоит в том, чтобы либо представлять код в виде последовательности байтов (либо в виде байтового массива, либо "сплющенного" в 32-битный примитив) или в виде строки. Принятый ответ преобразуется в UTF32, но это не всегда идеально.

Это код, который мы используем для разделения строки на свои кодовые элементы юникода, но с сохранением собственной кодировки UTF-16. Результат является перечислимым, который может использоваться для сравнения (под) строк изначально в С#/. NET:

    public class InvalidEncodingException : System.Exception
    { }

    public static IEnumerable<string> UnicodeCodepoints(this string s)
    {
        for (int i = 0; i < s.Length; ++i)
        {
            if (Char.IsSurrogate(s[i]))
            {
                if (s.Length < i + 2)
                {
                    throw new InvalidEncodingException();
                }
                yield return string.Format("{0}{1}", s[i], s[++i]);
            }
            else
            {
                yield return string.Format("{0}", s[i]);
            }
        }
    }
}

Ответ 5

public static string ToCodePointNotation(char c)
{

    return "U+" + ((int)c).ToString("X4");
}

Console.WriteLine(ToCodePointNotation('a')); //U+0061

Ответ 6

Я нашел небольшой метод на форуме msdn. Надеюсь, это поможет.

    public int get_char_code(char character){ 
        UTF32Encoding encoding = new UTF32Encoding(); 
        byte[] bytes = encoding.GetBytes(character.ToString().ToCharArray()); 
        return BitConverter.ToInt32(bytes, 0); 
    }