UTF-8 String in RichTextBox anzeigen



  • In meinem Programm geht es u.a. darum, Dateinamen und andere Protokoll-Hinweise in einer RichTextBox anzuzeigen. Das mache ich mit

     richTextBox1.AppendText(Zeile + (Environment.NewLine));
    

    Wenn in "Zeile" ein Dateiname steht, der bestimmte Sonderzeichen enth├Ąlt, dann werden diese nicht korrekt angezeigt

    Zeile = "Hase Handy­čĺť 5ÔéČ Test.jpg"

    Das Herz-Symbol ­čĺť wird als Quadrat angezeigt.
    Intern ist alles OK, im Debugger sehe ich das Herz-Symbol.

    Muss man bei der RichTextBox irgendwo angeben, dass es sich bei dem Text um UTF-8 handelt ?
    Das ÔéČ-Zeichen (Hex = E2 82 AC) wird korrekt angezeigt.

    Das ­čĺť-Zeichen wird intern als folgender Hex-Code dargestellt: F0 9F 92 9C

    Wenn ich den Text aus der RichTextBox kopiere und in ein Edit-Fenster einf├╝ge, wird dort wieder das Herz-Symbol angezeigt, es ist also korrekt in der RichTextBox gespeichert, wird nur nicht richtig angezeigt.

    Als Font habe ich Courier New eingestellt.



  • Die Winforms controls bei .Net k├Ânnen kein UTF-8 sondern nur UTF-16 (welches auch die default kodierung der klasse string ist)
    Daher UTF-8 -> UTF-16 konvertieren vor der anzeige.
    Allgemein kann die windows API nichts mit UTF-8 anfangen



  • @firefly ,
    Danke f├╝r den Hinweis.
    Ich benutze nun statt der RichTextBox ein ListView, da werden alle Zeichen korrekt dargestellt.



  • Und welchen Zeichensatz hast du da eingestellt? Ich denke, es liegt nur daran, da├č der Zeichensatz ("Courier New") dieses Zeichen nicht enth├Ąlt (und daher dann das Fallback-Zeichen, welches meistens ein Rechteck ist, darstellt).



  • @Th69 ,
    ListView zeigt auch bei Courier New diese Zeichen korrekt an.
    Ich habe auch noch andere Codes getestet, alle funktionieren.
    https://www.compart.com/de/unicode/U+1F49C
    Es wird schon so sein, wie firefly bereits sagte, dass die RichTextBox keine vollst├Ąndige UTF-8 Unterst├╝tzung besitzt.



  • Was @firefly dir sagen wollte, ist, da├č keines der Windows-Controls direkt UTF-8 Unterst├╝tzung bietet, sondern immer Strings im UTF-16 Encoding angegeben werden m├╝ssen.
    Die Darstellung von Zeichen ist immer eine Frage der Darstellung des eingestellten Zeichensatzes.

    Jedoch habe ich auch keine Erkl├Ąrung, warum es bei der RichTextBox nicht funktioniert.
    Da m├╝├čtest du etwas mehr Code zeigen.



  • Ohne eine L├Âsung zu haben (auch abseits von UTF-8/16 und auch C#).

    @Th69 sagte in UTF-8 String in RichTextBox anzeigen:

    Und welchen Zeichensatz hast du da eingestellt? Ich denke, es liegt nur daran, da├č der Zeichensatz ("Courier New") dieses Zeichen nicht enth├Ąlt (und daher dann das Fallback-Zeichen, welches meistens ein Rechteck ist, darstellt).

    Nur ein schneller Test:
    https://i.imgur.com/gtKHqBy.png
    Links ein normales Editcontrol, rechts Richedit. Reinkopiert jeweils ├╝ber die Zwischenablage, gleiche Schriftart eingew├Ąhlt (lfStatusFont aus SystemParametersInfo).
    Dieses Verhalten h├Ątte ich jetzt auch nicht erwartet.



  • Welche .NET-Version benutzt du? Ab Version 4.7 ist das wohl gefixt (es wurde vorher intern eine ├Ąltere Version des WinAPI RichEdit-Controls benutzt, s.a. RichTextBox cannot display Unicode Mathematical alphanumeric symbols).

    Falls du nicht upgraden kannst oder m├Âchtest, so k├Ânntest du den Workaround benutzen (also ein eigenes davon abgeleitetes Control erstellen).



  • @hkdd sagte in UTF-8 String in RichTextBox anzeigen:

    Es wird schon so sein, wie firefly bereits sagte, dass die RichTextBox keine vollst├Ąndige UTF-8 Unterst├╝tzung besitzt.

    N├ das hat mit UTF-8 gar nix zu tun. Windows tut immer mit UTF-16 und C# tut immer UTF-16. Und da UTF-8 und UTF-16 grundverschieden sind, liegt es sicher nicht daran dass du UTF-8 wo rein f├╝tterst wo UTF-16 sein sollte. Sonst w├Ąre jedes 2. Zeichen ein Kasterl.

    omit es vermutlich was zu tun hat ist der Rendering-Code der beiden Controls. Courier New & Co. haben lange nicht Glyphen f├╝r alles was Unicode so kann. Das normale Edit Control verwendet Funktionen wo Windows automatisch einen "Ersatzfont" ausw├Ąhlt um die fehlenden Zeichen auszugeben.

    Vermutung: Da das Richedit Control aber mehr "kann" (unterschiedliche Formatierung einzelner W├Ârter/Zeichen etc.), muss es mehr selbst machen. Daher kann es die einfachen Text-Ausgabefunktionen (wo Windows die ganze Show vonwegen Ersatzfont suchen erledigt) nicht verwenden. Weil man bei denen nur einen Font/Gr├Âsse/Farbe etc. f├╝r alles angeben kann. Und da es keinen eigenen Code f├╝r Ersatzfont Suchen hat, wird alles was im ausgew├Ąhlten Font fehlt einfach als Kasterl angezeigt.



  • Ich habe jetzt noch etwas mit Delphi 10.3 getestet.
    Da wird in einem TRichEdit-Fenster auch nur ein Quadrat, statt Herz angezeigt und in einem TListBox-Fenster ist alles OK.
    Der gleiche Effekt, wie von @yahendrik auch f├╝r C# festgestellt.
    Die Strings sind immer UTF8.


  • Administrator

    @hkdd sagte in UTF-8 String in RichTextBox anzeigen:

    Die Strings sind immer UTF8.

    Mich w├╝rde ja mal interessieren, wie du weisst, dass es sich um UTF-8 handelt. Die Enkodierung ist vielfach so transparent, dass du gar nicht mitbekommst, dass sich diese irgendwo ├Ąndert. Schliesse mich Th69 und hustbaer an. Das hat nichts mit UTF-8 oder UTF-16 zu tun.



  • Ich habe jetzt selber mal den von mir beschriebenen Workaround (ExRichText) mit einem kleinen C# WinForms Programm ausprobiert und zumindestens unter Win10 funktioniert es (w├Ąhrend die .NET 4 RichTextBox das Herzchen wirklich nicht richtig anzeigt).

    Unter Win7 wird das Zeichen jedoch von keinem Standardcontrol (auch nicht dem Editor/TextBox) angezeigt, also nur als Rechteck dargestellt.
    Jedoch wird es vom VS 2015 korrekt im Texteditor dargestellt!

    @hkdd: Unsere Aussagen bzgl. UTF-8 und UTF-16 hast du anscheinend immer noch begriffen?!



  • @Th69 ,
    offenbar habe ich da etwas falsch angenommen.
    Zumindest die CS-Codedateien mit dem VS-Editor bearbeitet, haben das UTF8-Format und am Anfang auch einen UTF8-BOM = EF BB BF.
    Das Standard-string-Format ist UTF-16 = Unicode, wie hier ganz klar genannt:
    https://docs.microsoft.com/de-de/dotnet/standard/base-types/character-encoding

    Wenn man mit dieser Faktenlage sich ├╝berlegt, warum eine string-Variable, die das Herz-Symbol korrekt enth├Ąlt (im Unicode-Zeichensatz), die man in ein string[]-Array einer RichTextBox, welches ja demnach auch im Unicode-Format dargestellt sein sollte, in der RichTextBox nicht als Herz-Symbol dargestellt wird.
    Demnach ist string nicht immer gleich string. Oder doch ?



  • @hkdd sagte in UTF-8 String in RichTextBox anzeigen:

    Demnach ist string nicht immer gleich string. Oder doch ?

    String ist String. Encoding ist Encoding.



  • @Swordfish
    Das Encoding l├Ąuft dabei unaufgefordert ab.
    Ich habe mal ein ganz kleines Testprogramm gemacht

    using System;
    using System.IO;
    namespace StringTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                StreamWriter Ausgabe = new StreamWriter(@"L:\StringTest.txt");
                Ausgabe.WriteLine("H­čĺťEÔéČ");
                Ausgabe.Close();
                Environment.Exit(0);
            }
        }
    }
    

    Da ist kein Encoding drin. Von UTF8 ist auch nirgendwo die Rede.
    Die erstellte Datei sieht folgenderma├čen aus:

    H­čĺťEÔéČ
    

    Und im Hex-Listing..

     48 F0 9F 92  9C 45 E2 82  AC 0D 0A    
    

    "H" = 0x48
    "­čĺť" = 0xF0 9F 92 9C
    "E" = 0x45
    "ÔéČ" = 0xE2 82 AC
    0D 0A ist der Zeilenabschluss.

    Es handelt sich eindeutig um UTF8 (ohne BOM).



  • @Th69 sagte in UTF-8 String in RichTextBox anzeigen:

    Welche .NET-Version benutzt du? Ab Version 4.7 ist das wohl gefixt

    das k├Ânnte die Ursache sein (werde ich probieren).
    Ich benutze f├╝r bestimmte Programme die 4 (nicht 4.7),
    weil nur dadurch diese Programme auch unter XP funktionieren.



  • Dann nimm den von mir oben beschriebenen Workaround (jedoch wird das Herzchen dann wohl auch nicht unter XP angezeigt werden, wenn es schon nicht f├╝r Win7 klappt).

    Mit welcher Windows-Version hast du es denn erstellt und getestet?

    Und beim StreamWriter ist UTF-8 das Standard-Encoding (wenn man es nicht explizit angibt), aber ohne BOM: StreamWriter(string) (s. Hinweise)
    So gesehen liefert dein Testprogramm jetzt nichts Interessantes.


  • Administrator

    @hkdd Die dotNet String Klasse verwendet intern UTF-16. Der StreamWriter schreibt standardm├Ąssig mit UTF-8. Findest du in der Dokumentation:

    This constructor creates a StreamWriter with UTF-8 encoding without a Byte-Order Mark (BOM), so its GetPreamble method returns an empty byte array.

    Das Problem ist die Darstellung und diese wird von Fonts und Controls ├╝bernommen. Und es gibt viele unterschiedliche Arten von Fonts. Und gewisse Controls k├Ânnen mit gewissen Fonts oder spezifischen Zeichen nicht umgehen. Daher hat dies nichts mit Enkodierung oder Unicode zu tun. Hier geht es nur um die Darstellung.

    UTF-8, UTF-16 und UTF-32 sagen nichts ├╝ber die Darstellung aus. Das sind ausschliesslich Definitionen, wie die rohen Textdaten (also Code points) gespeichert werden sollen.



  • @Th69 sagte in UTF-8 String in RichTextBox anzeigen:

    Mit welcher Windows-Version hast du es denn erstellt und getestet?

    Mit Win10-Pro-64 1903



  • @Dravere sagte in UTF-8 String in RichTextBox anzeigen:

    @hkdd Die dotNet String Klasse verwendet intern UTF-16. Der StreamWriter schreibt standardm├Ąssig mit UTF-8. Findest du in der Dokumentation:

    This constructor creates a StreamWriter with UTF-8 encoding without a Byte-Order Mark (BOM), so its GetPreamble method returns an empty byte array.

    Das Problem ist die Darstellung und diese wird von Fonts und Controls ├╝bernommen. Und es gibt viele unterschiedliche Arten von Fonts. Und gewisse Controls k├Ânnen mit gewissen Fonts oder spezifischen Zeichen nicht umgehen. Daher hat dies nichts mit Enkodierung oder Unicode zu tun. Hier geht es nur um die Darstellung.

    UTF-8, UTF-16 und UTF-32 sagen nichts ├╝ber die Darstellung aus. Das sind ausschliesslich Definitionen, wie die rohen Textdaten (also Code points) gespeichert werden sollen.

    Das ist richtig. Nur soweit ich weis ist UTF-8 Support in .Net selbst f├╝r Controls nicht vorgesehen sonder UTF-16 (Das ist die standard UNICODE Kodierung von Windows)
    Daher sollte man das ganze nochmal pr├╝fen, wenn man den UTF-8 String (Der bestimmt nicht als C# String vorhanden ist, da die String klasse UTF-16 verwendet) nach UTF-16 konvertiert wird bevor es dem Control ├╝bergeben wird


Log in to reply