2009-09-02 10 views
16

Ich versuche, Unicode-String in RTF-Format auszugeben. (Unter Verwendung von C# und WinForms)Wie Unicode-String in RTF ausgegeben wird (mit C#)

From wikipedia:

Wenn ein Unicode-Escape erforderlich ist, das Steuerwort \ u verwendet wird, gefolgt von einer 16-Bit-signierten ganzen Dezimalzahl der Unicode-Codepoint-Nummer gibt. Für Programme ohne Unicode-Unterstützung muss die nächste Darstellung dieses Zeichens in der angegebenen Codepage folgen. Zum Beispiel, \ u1576? würde den arabischen Buchstaben beh geben und angeben, dass ältere Programme, die keine Unicode-Unterstützung haben, diese stattdessen als Fragezeichen darstellen sollten.

Ich weiß nicht, wie Unicode-Zeichen in Unicode-Codepunkt ("\ u1576") konvertiert werden. Konvertierung in UTF 8, UTF 16 und ähnliche ist einfach, aber ich weiß nicht, wie in Codepoint konvertieren.

Szenario, in dem ich diese verwenden:

  • I RTF-Datei in String lesen vorhandene (ich lese Vorlage)
  • string.replace # TOKEN # mit MyUnicodeString (Vorlage mit Daten)
  • schreiben Sie das Ergebnis in eine andere RTF-Datei.

Problem entstehen, wenn Unicode-Zeichen

angekommen

Antwort

25

Vorausgesetzt, dass alle Zeichen, die Sie für exist Catering sind im Basic Multilingual Plane (es ist unwahrscheinlich dass Sie mehr brauchen), dann sollte eine einfache UTF-16-Codierung ausreichen.

Wikipedia:

Alle möglichen Codepunkte von U + 0000 bis U + 10FFFF, mit Ausnahme der Surrogat-Codepunkten U + D800-U + DFFF (die nicht Zeichen), sind eindeutig zugeordnet von UTF-16 unabhängig der aktuellen oder zukünftigen des Codepunkts Zeichenzuweisung oder verwenden.

Das folgende Beispielprogramm veranschaulicht entlang der Linien von etwas zu tun, was Sie wollen:

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(); 
} 

Das wichtige Bit ist die Convert.ToUInt32(c) die im Wesentlichen den Codepunktwert für das fragliche Zeichen zurückgibt.Der RTF-Escape für Unicode erfordert einen Dezimal-Unicode-Wert. Die Codierung System.Text.Encoding.Unicode entspricht UTF-16 gemäß der MSDN-Dokumentation.

+0

hmmmm, sehr interessanter Punkt.Wenn das wahr ist, dann liegt wahrscheinlich irgendwo ein Fehler in meiner Logik ... und Ian Kemps Antwort macht viel mehr Sinn ... Ich werde weiter googlen – Emir

+0

Danke zum Beispiel, es funktioniert! – Emir

1

Sie den String in eine byte[] Array umwandeln müssen (mit Encoding.Unicode.GetBytes(string)), dann die Schleife durch das Array und prepend ein \ und u Zeichen für alle Sie Unicode-Zeichen finden. Wenn Sie das Array dann wieder in eine Zeichenfolge konvertieren, müssen Sie die Unicode-Zeichen als Zahlen belassen.

Zum Beispiel, wenn Ihr Array wie folgt aussieht:

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

es würde:

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

Hallo, vielen Dank für Ihre Antwort, Ich habe versucht, Ihre Lösung zu implementieren, leider funktioniert es nicht. Ich denke, das liegt daran, dass es einen Unterschied zwischen Codepoint und UTF16-Codierung gibt (Encoding.Unicode) Sie schlagen vor, dass ich Bytes aus UTF16-Codierung ausgeben, wo Codepoint ausgenommen ist. (Und das funktioniert für viele Zeichen, aber nicht für alle) – Emir

+0

Diese Antwort funktioniert auch, Ich hatte wahrscheinlich einen Fehler in meinem Code, als ich es getestet habe. Vielen Dank für Ihre Antwort und Ihre Zeit – Emir

+0

Das einzige Problem hier ist, wenn Sie in ein Byte-Array konvertieren, verlieren Sie Ihre Codierung. Am besten lassen Sie es als UTF-16 und durchlaufen Sie es. – Brain2000

18

Fest Code aus akzeptierter Antwort - Sonderzeichen zu entkommen, wie in diesen link

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(); 
} 
0

Auf der Grundlage der Beschreibung sind einige Code in Java hier hinzugefügt, und arbeitet getestet:

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(); 
} 

Wichtig ist, dass Sie 2 Zeichen (in der Nähe des Unicode-Zeichens oder einfach nur?) Nach dem Escape-Code einfügen müssen. weil die Unicode 2 Bytes belegen.

Auch die Spezifikation sagt, dass Sie negativen Wert verwenden sollten, wenn der Codepunkt größer als 32767 ist, aber in meinem Test ist es in Ordnung, wenn Sie keinen negativen Wert verwenden. Hier

ist die spec:

\ uN Dieses Schlüsselwort ein einzelnes Unicode-Zeichen darstellt, die keine Entsprechung ANSI Darstellung auf der aktuellen Seite ANSI Code basiert hat. N stellt den Unicode-Zeichenwert dar, der als Dezimalzahl ausgedrückt wird. Auf dieses Schlüsselwort folgen sofort äquivalente Zeichen in ANSI-Darstellung. Auf diese Weise ignorieren alte Leser das Schlüsselwort \ uN und nehmen die ANSI-Darstellung richtig auf. Wenn dieses Schlüsselwort gefunden wird, sollte der Leser die nächsten N Zeichen ignorieren, wobei N dem letzten gefundenen \ ucN-Wert entspricht.

Wie bei allen RTF-Schlüsselwörtern kann ein Schlüsselwortbeendigungsbereich vorhanden sein (vor den ANSI-Zeichen), der in den zu überspringenden Zeichen nicht berücksichtigt wird. Obwohl dies nicht wahrscheinlich ist (oder empfohlen wird), werden ein \ bin-Schlüsselwort, sein Argument und die folgenden Binärdaten als ein Zeichen zum Überspringen von Zwecken betrachtet. Wenn beim Scannen überspringbarer Daten ein RTF-Bereichsbegrenzungszeichen (also eine öffnende oder schließende geschweifte Klammer) angetroffen wird, werden die überspringbaren Daten als vor dem Begrenzungszeichen beendet betrachtet. Dies ermöglicht es einem Leser, eine rudimentäre Fehlerbehebung durchzuführen. Um ein RTF-Trennzeichen in überspringbare Daten einzufügen, muss es wie im Klartext mit dem entsprechenden Kontrollsymbol dargestellt werden (dh mit einem umgekehrten Schrägstrich versehen). Jedes RTF-Steuerwort oder -Symbol wird zum Zählen überspringbarer Zeichen als ein einzelnes Zeichen betrachtet.

Wenn ein RTF-Writer auf ein Unicode-Zeichen ohne entsprechendes ANSI-Zeichen stößt, sollte er \ uN gefolgt von der besten ANSI-Darstellung ausgeben, die er verwalten kann. Wenn das Unicode-Zeichen in einen ANSI-Zeichenstrom konvertiert wird, dessen Anzahl sich von der aktuellen Unicode-Zeichenbyteanzahl unterscheidet, sollte das Schlüsselwort \ ucN vor dem Schlüsselwort \ uN ausgegeben werden, um den Leser über die Änderung zu informieren.

RTF-Steuerwörter akzeptieren im Allgemeinen signierte 16-Bit-Zahlen als Argumente. Aus diesem Grund müssen Unicode-Werte größer als 32767 als negative Zahl ausgedrückt werden

Verwandte Themen