Возвращать кодовую точку символов в С#
Как я могу вернуть Unicode Code Point символа? Например, если вход "A", то выход должен быть "U + 0041". В идеале, решение должно позаботиться о суррогатных парах.
С кодовой точкой я имею в виду фактическую кодовую точку в соответствии с Unicode, которая отличается от блок кода (UTF8 имеет 8-битные кодовые единицы, UTF16 имеет 16-битные кодовые единицы, а UTF32 имеет 32-битные кодовые единицы, в последнем случае значение равно кодовой точке, после учета энтузиазма).
Ответы
Ответ 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);
}