utf8 unidades una texto secuencia representa example como codigo codificar caracteres c# string unicode char astral-plane

c# - unidades - ¿Cómo obtendría una matriz de puntos de código Unicode de una cadena.NET?



encoding utf-8 c# (4)

No parece que deba ser mucho más complicado que esto:

public static IEnumerable<int> Utf32CodePoints( this IEnumerable<char> s ) { bool useBigEndian = !BitConverter.IsLittleEndian; Encoding utf32 = new UTF32Encoding( useBigEndian , false , true ) ; byte[] octets = utf32.GetBytes( s ) ; for ( int i = 0 ; i < octets.Length ; i+=4 ) { int codePoint = BitConverter.ToInt32(octets,i); yield return codePoint; } }

Tengo una lista de restricciones de rango de caracteres con las que necesito verificar una cadena, pero el tipo de char en .NET es UTF-16 y, por lo tanto, algunos caracteres se vuelven pares extraños (sustitutos). Por lo tanto, al enumerar todos los caracteres en una string , no obtengo los puntos de código Unicode de 32 bits y algunas comparaciones con valores altos fallan.

Entiendo a Unicode lo suficientemente bien como para analizar los bytes si es necesario, pero estoy buscando una solución BCL para C # / .NET Framework. Asi que ...

¿Cómo convertiría una string a una matriz ( int[] ) de puntos de código Unicode de 32 bits?


Se me ocurrió el mismo enfoque sugerido por Nicholas (y Jeppe), pero más corto:

public static IEnumerable<int> GetCodePoints(this string s) { var utf32 = new UTF32Encoding(!BitConverter.IsLittleEndian, false, true); var bytes = utf32.GetBytes(s); return Enumerable.Range(0, bytes.Length / 4).Select(i => BitConverter.ToInt32(bytes, i * 4)); }

La enumeración era todo lo que necesitaba, pero obtener una matriz es trivial:

int[] codePoints = myString.GetCodePoints().ToArray();


Usted está preguntando acerca de los puntos de código . En UTF-16 (C # ''s char ) solo hay dos posibilidades:

  1. El carácter es del plano básico multilingüe y está codificado por una sola unidad de código.
  2. El carácter está fuera de la BMP y se codifica utilizando un par de unidades de código alto-bajo surrogare

Por lo tanto, asumiendo que la cadena es válida, esto devuelve una matriz de puntos de código para una cadena dada:

public static int[] ToCodePoints(string str) { if (str == null) throw new ArgumentNullException("str"); var codePoints = new List<int>(str.Length); for (int i = 0; i < str.Length; i++) { codePoints.Add(Char.ConvertToUtf32(str, i)); if (Char.IsHighSurrogate(str[i])) i += 1; } return codePoints.ToArray(); }

Un ejemplo con un par suplente 🌀 y un carácter compuesto ñ :

ToCodePoints("/U0001F300 El Ni/u006E/u0303o"); // 🌀 El Niño // { 0x1f300, 0x20, 0x45, 0x6c, 0x20, 0x4e, 0x69, 0x6e, 0x303, 0x6f } // 🌀 E l N i n ̃◌ o

Aquí hay otro ejemplo. Estos dos puntos de código representan una nota musical número 32 con un acento de staccato, ambos pares sustitutos:

ToCodePoints("/U0001D162/U0001D181"); // 𝅘𝅥𝅰𝆁 // { 0x1d162, 0x1d181 } // 𝅘𝅥𝅰 𝆁◌

Cuando C-normalized , se descomponen en una cabeza de nota, combinando raíz, combinando bandera y combinando acento-staccato, todos los pares sustitutos:

ToCodePoints("/U0001D162/U0001D181".Normalize()); // 𝅘𝅥𝅰𝆁 // { 0x1d158, 0x1d165, 0x1d170, 0x1d181 } // 𝅘 𝅥 𝅰 𝆁◌

Tenga en cuenta que la solución de leppie no es correcta. La pregunta es sobre puntos de código , no elementos de texto . Un elemento de texto es una combinación de puntos de código que juntos forman un solo grafema. Por ejemplo, en el ejemplo anterior, la ñ en la cadena está representada por una minúscula latina n seguida de una tilde combinada ̃◌ . La solución de Leppie descarta cualquier carácter de combinación que no pueda normalizarse en un solo punto de código.


Esta respuesta no es correcta. Vea la respuesta de @ Virtlink para la correcta.

static int[] ExtractScalars(string s) { if (!s.IsNormalized()) { s = s.Normalize(); } List<int> chars = new List<int>((s.Length * 3) / 2); var ee = StringInfo.GetTextElementEnumerator(s); while (ee.MoveNext()) { string e = ee.GetTextElement(); chars.Add(char.ConvertToUtf32(e, 0)); } return chars.ToArray(); }

Notas : Se requiere la normalización para tratar con caracteres compuestos.