Cómo dar salida a una cadena Unicode a RTF (usando C #)

Estoy tratando de dar salida a la cadena Unicode en formato RTF. (usando c # y winforms)

De la wikipedia :

Si se requiere un escape Unicode, se utiliza la palabra de control \ u, seguida de un entero decimal con signo de 16 bits que proporciona el número de punto de código Unicode. Para el beneficio de progtwigs sin soporte Unicode, esto debe ir seguido de la representación más cercana de este carácter en la página de códigos especificada. Por ejemplo, \ u1576? daría la letra arábica beh, especificando que los progtwigs anteriores que no tienen soporte Unicode deberían representarlo como un signo de interrogación.

No sé cómo convertir el carácter Unicode en el punto de código Unicode (“\ u1576”). La conversión a UTF 8, UTF 16 y similar es fácil, pero no sé cómo convertir a código.

Escenario en el que uso esto:

  • Leo el archivo RTF existente en una cadena (estoy leyendo la plantilla)
  • string.replace # TOKEN # con MyUnicodeString (la plantilla se rellena con datos)
  • escribir el resultado en otro archivo RTF.

Problema, surgen cuando llegaron los caracteres Unicode

Siempre que todos los personajes que estás atendiendo existan en el plano multilingüe básico (es poco probable que necesites algo más), entonces una simple encoding UTF-16 debería ser suficiente.

Wikipedia:

Todos los puntos de código posibles desde U + 0000 hasta U + 10FFFF, excepto los puntos de código sustituto U + D800-U + DFFF (que no son caracteres), están mapeados de forma exclusiva por UTF-16 independientemente de la asignación de caracteres actual o futura del punto de código o usar.

El siguiente progtwig de ejemplo ilustra hacer algo en la línea de lo que desea:

static void Main(string[] args) { // ë char[] ca = Encoding.Unicode.GetChars(new byte[] { 0xeb, 0x00 }); var sw = new StreamWriter(@"c:/helloworld.rtf"); sw.WriteLine(@"{\rtf {\fonttbl {\f0 Times New Roman;}} \f0\fs60 H" + GetRtfUnicodeEscapedString(new String(ca)) + @"llo, World! }"); sw.Close(); } static string GetRtfUnicodeEscapedString(string s) { var sb = new StringBuilder(); foreach (var c in s) { if (c <= 0x7f) sb.Append(c); else sb.Append("\\u" + Convert.ToUInt32(c) + "?"); } return sb.ToString(); } 

El bit importante es Convert.ToUInt32(c) que esencialmente devuelve el valor del punto de código para el personaje en cuestión. El escape RTF para Unicode requiere un valor Unicode decimal. La encoding System.Text.Encoding.Unicode corresponde a UTF-16 según la documentación de MSDN.

Se arregló el código de la respuesta aceptada – se agregó el carácter especial de escape, como se describe en este enlace

 static string GetRtfUnicodeEscapedString(string s) { var sb = new StringBuilder(); foreach (var c in s) { if(c == '\\' || c == '{' || c == '}') sb.Append(@"\" + c); else if (c <= 0x7f) sb.Append(c); else sb.Append("\\u" + Convert.ToUInt32(c) + "?"); } return sb.ToString(); } 

Tendrá que convertir la cadena en una matriz de byte[] (usando Encoding.Unicode.GetBytes(string) ), luego recorrer esa matriz y anteponer un carácter \ y u a todos los caracteres Unicode que encuentre. Cuando vuelva a convertir la matriz en una cadena, tendrá que dejar los caracteres Unicode como números.

Por ejemplo, si su matriz se ve así:

 byte[] unicodeData = new byte[] { 0x15, 0x76 }; 

se convertiría en:

 // 5c = \, 75 = u byte[] unicodeData = new byte[] { 0x5c, 0x75, 0x15, 0x76 }; 

Según la especificación, aquí hay un código en java que se prueba y funciona:

  public static String escape(String s){ if (s == null) return s; int len = s.length(); StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++){ char c = s.charAt(i); if (c >= 0x20 && c < 0x80){ if (c == '\\' || c == '{' || c == '}'){ sb.append('\\'); } sb.append(c); } else if (c < 0x20 || (c >= 0x80 && c <= 0xFF)){ sb.append("\'"); sb.append(Integer.toHexString(c)); }else{ sb.append("\\u"); sb.append((short)c); sb.append("??");//two bytes ignored } } return sb.toString(); } 

Lo importante es que necesita agregar 2 caracteres (cerca del carácter Unicode o simplemente usar? En su lugar) después de descifrar el código. porque el Unicode ocupa 2 bytes.

Además, la especificación dice que debería usar un valor negativo si el código es mayor que 32767, pero en mi prueba, está bien si no usa un valor negativo.

Aquí está la especificación:

\ uNEsta palabra clave representa un único carácter Unicode que no tiene una representación ANSI equivalente basada en la página actual de códigos ANSI. N representa el valor del carácter Unicode expresado como un número decimal. Esta palabra clave es seguida inmediatamente por caracteres equivalentes en representación ANSI. De esta forma, los lectores antiguos ignorarán la palabra clave \ uN y elegirán la representación ANSI correctamente. Cuando se encuentra esta palabra clave, el lector debe ignorar los siguientes N caracteres, donde N corresponde al último valor de \ ucN encontrado.

Al igual que con todas las palabras clave RTF, un espacio de terminación de palabra clave puede estar presente (antes de los caracteres ANSI) que no se cuenta en los caracteres para omitir. Aunque es probable que esto no ocurra (o se recomiende), una palabra clave \ bin, su argumento y los datos binarios que siguen se consideran un solo carácter para saltarse los objectives. Si se encuentra un carácter delimitador de scope RTF (es decir, un corsé de apertura o cierre) mientras se escanean datos que se pueden omitir, se considera que los datos que se pueden omitir finalizan antes que el delimitador. Esto hace posible que un lector realice una recuperación de error rudimentaria. Para incluir un delimitador RTF en datos que se pueden omitir, se debe representar utilizando el símbolo de control apropiado (es decir, escapado con una barra diagonal inversa) como en texto sin formato. Cualquier palabra o símbolo de control RTF se considera un solo carácter a los efectos de contar los caracteres que se pueden omitir.

Un escritor RTF, cuando encuentra un carácter Unicode sin el carácter ANSI correspondiente, debe dar como resultado \ uN seguido de la mejor representación ANSI que pueda gestionar. Además, si el carácter Unicode se traduce en una secuencia de caracteres ANSI con un recuento de bytes que difiere del Conteo de bytes de caracteres Unicode actual, debe emitir la palabra clave \ ucN antes de la palabra clave \ uN para notificar al lector del cambio.

Las palabras de control RTF generalmente aceptan números de 16 bits con signo como argumentos. Por este motivo, los valores Unicode mayores que 32767 se deben express como números negativos