objective-c unicode nsstring

objective c - ¿Cómo convertir un valor unichar a un NSString en Objective-C?



unicode (5)

Tengo un personaje internacional almacenado en una variable unichar. Este personaje no proviene de un archivo o url. La variable en sí misma solo almacena un corto sin firmar (0xce91) que está en formato UTF-8 y se traduce a la letra griega mayúscula ''A''. Intento poner ese personaje en una variable NSString pero fallaré miserablemente.

He intentado de 2 maneras diferentes que fracasaron:

unichar greekAlpha = 0xce91; //could have written greekAlpha = ''Α'' instead. NSString *theString = [NSString stringWithFormat:@"Greek Alpha: %C", greekAlpha];

No es bueno. Obtengo algunos personajes chinos extraños. Como nota al margen, esto funciona perfectamente con los personajes ingleses.

Entonces también intenté esto:

NSString *byteString = [[NSString alloc] initWithBytes:&greekAlpha length:sizeof(unichar) encoding:NSUTF8StringEncoding];

Pero esto tampoco funciona. Obviamente estoy haciendo algo terriblemente mal, pero no sé qué. Puede alguien ayudarme por favor ? ¡Gracias!


Aquí hay un algoritmo para la codificación UTF-8 en un solo carácter:

if (utf8char<0x80){ chars[0] = (utf8char>>0) & (0x7F | 0x00); chars[1] = 0x00; chars[2] = 0x00; chars[3] = 0x00; } else if (utf8char<0x0800){ chars[0] = (utf8char>>6) & (0x1F | 0xC0); chars[1] = (utf8char>>0) & (0x3F | 0x80); chars[2] = 0x00; chars[3] = 0x00; } else if (utf8char<0x010000) { chars[0] = (utf8char>>12) & (0x0F | 0xE0); chars[1] = (utf8char>>6) & (0x3F | 0x80); chars[2] = (utf8char>>0) & (0x3F | 0x80); chars[3] = 0x00; } else if (utf8char<0x110000) { chars[0] = (utf8char>>18) & (0x07 | 0xF0); chars[1] = (utf8char>>12) & (0x3F | 0x80); chars[2] = (utf8char>>6) & (0x3F | 0x80); chars[3] = (utf8char>>0) & (0x3F | 0x80); }


Como 0xce91 está en formato UTF-8 y %C espera que esté en UTF-16, una solución simple como la anterior no funcionará. Para que stringWithFormat:@"%C" funcione, debe ingresar 0x391 que es el UTF-16 unicode.

Para crear una cadena del unichar codificado con UTF-8, primero debe dividir el Unicode en sus octetos y luego usar initWithBytes:length:encoding .

unichar utf8char = 0xce91; char chars[2]; int len = 1; if (utf8char > 127) { chars[0] = (utf8char >> 8) & (1 << 8) - 1; chars[1] = utf8char & (1 << 8) - 1; len = 2; } else { chars[0] = utf8char; } NSString *string = [[NSString alloc] initWithBytes:chars length:len encoding:NSUTF8StringEncoding];


El código anterior es el equivalente moral de unichar foo = ''abc''; .

El problema es que ''Α'' no se asigna a un solo byte en el "conjunto de caracteres de ejecución" (supongo que UTF-8) que es "definido por la implementación" en C99 §6.4.4.4 10:

El valor de una constante de caracteres enteros que contiene más de un carácter (por ejemplo, ''ab'' ) o que contiene un carácter o secuencia de escape que no se correlaciona con un carácter de ejecución de un solo byte, está definido por la implementación.

Una forma es hacer que ''ab'' igual a ''a''<<8|b . Algunos encabezados de sistema Mac / iOS se basan en esto para cosas como OSType / FourCharCode / FourCC ; el único en iOS que me viene a la mente es el formato de píxeles CoreVideo. Esto es, sin embargo, inportable.

Si realmente quieres un literal unichar , puedes probar L''A'' (técnicamente es un literal wchar_t , pero en OS X e iOS, wchar_t suele ser UTF-16, por lo que funcionará para las cosas dentro del BMP). Sin embargo, es mucho más simple usar @"Α" (que funciona siempre que establezca la codificación de caracteres de origen correctamente) o @"/u0391" (que ha funcionado desde al menos el iOS 3 SDK).


La respuesta anterior es excelente, pero no representa los caracteres UTF-8 de más de 16 bits, por ejemplo, el símbolo de puntos suspensivos: 0xE2,0x80,0xA6. Aquí hay un ajuste al código:

if (utf8char > 65535) { chars[0] = (utf8char >> 16) & 255; chars[1] = (utf8char >> 8) & 255; chars[2] = utf8char & 255; chars[3] = 0x00; } else if (utf8char > 127) { chars[0] = (utf8char >> 8) & 255; chars[1] = utf8char & 255; chars[2] = 0x00; } else { chars[0] = utf8char; chars[1] = 0x00; } NSString *string = [[[NSString alloc] initWithUTF8String:chars] autorelease];

Tenga en cuenta el método de inicialización de cadena diferente que no requiere un parámetro de longitud.


unichar greekAlpha = 0x0391; NSString* s = [NSString stringWithCharacters:&greekAlpha length:1];

Y ahora puedes incorporar ese NSString a otro de la manera que quieras. Tenga en cuenta, sin embargo, que ahora es legal escribir un alfa griego directamente en un literal NSString.