China, China, China ...

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    China, China, China ...

    Hi, ihr LIeben,

    ich habe ein vertracktes Problem, dass mich schier zur Verzweiflung treibt. Offensichtlich fehlt mir hier eine wichtige Information.

    Zur Sache:

    Ich habe eine List(of Structure), die ich in einer datagrid view darstelle. Hier der aktuelle Inhalt der Struktur. (s. Anhang 1)

    Wir haben also fünf Zeilen mit je zwei Spalten. Ich möchte diese List (of Structure) in einem sequentiellen File speichern. Dazu trenne ich die Felder der Struktur mit einem FLDSEP Charakter und beende das letzte Feld in der Zeile mit einem RECSEP.

    VB.NET-Quellcode

    1. Buffer &= saveDate.ToString & FLDSEP &
    2. TextList(i).entYear.ToString & FLDSEP &
    3. TextList(i).entText & RECSEP


    FLDSEP und RECSEP sind wie folgt definiert.

    VB.NET-Quellcode

    1. Public FLDSEP As Char = Convert.ToChar(&H0)
    2. Public RECSEP As Char = Convert.ToChar(&HFF)


    Das Ganze schreibe ich dann in einen sequentiellen File:

    VB.NET-Quellcode

    1. System.IO.File.WriteAllText(CALENDAROBJECT, Buffer)


    Soweit so gut.

    Aber wenn ich den Ausgabefile im Notepad anzeige, dann erhalte ich ein "chinesisches'" Display (s. Anhang 2).

    Na ja, da gibt es ja so Sachen wie die Byte Order Mask (BOM), wo solche Dinge festgeschrieben werden. Deshalb hab ich mir die Datei in meinem HexEditor angeschaut (s. Anhang 3).

    Offensichtlich ist keine BOM vorhanden. Der FLDSEP ist wie kodiert als x'00 eingefügt worden. Der RECSEP x'FF ist allerding als x'C3BF gespeichert worden. Warum auch immer.

    Und das scheint irgendwie ursächlich für dieses Problem zu sein. Denn wenn ich den RECSEP durch irgendein anderes Zeichen ersetze, etwa ';'c , dann verschwinden die "chinesischen" Schriftzeichen !

    Ich habe vermutet, dass der Beginn der Daten "29." = x'32392E als BOM interpretiert wird. Aber das ist wohl nicht Fall. Das Problem bleibt bestehen, wenn ich ein anderes Datum nehme. Und im übrigen würde das ja auch nicht zu der Tatsache passen, dass die Sache funktioniert, wenn man nur einen anderen RECSEP verwendete.

    WO um alles in der Welt "merkt" sich Windows, dass die Daten mit chinesichen Schriftzeichen dargestellt werden sollen ! Auch in den "properties" der Datei sehe ich nix. Ich bin ratlos !

    Wohlgemerkt, ich kann das Problem durch Wahl eines anderen RECSEP umgehen. Aber wie immer, würde ich halt gern verstehen was da los ist !

    Vielleicht kann mir jemand mit der üblichen Nachsicht weiter helfen ! Möglicherweise fehlt mir ja nur eine klitzekleine aber wichtige Information ! :)

    LG
    Peter
    Bilder
    • s 2017-11-01 12-58-294.jpg

      12,42 kB, 347×187, 86 mal angesehen
    • s 2017-11-01 12-59-385.jpg

      19,92 kB, 820×155, 91 mal angesehen
    • s 2017-11-01 13-19-333.jpg

      45,19 kB, 679×249, 101 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Peter329“ ()

    Peter329 schrieb:

    dann erhalte ich ein "chinesisches'" Display (s. Anhang 2).
    Welches Encoding verwendest Du bei .WriteAllText()?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich gebe gerade kein "explizites" Encoding an. Sonst wäre die Sache klar.

    Das ist die Anweisung mit der ich schreibe.

    VB.NET-Quellcode

    1. System.IO.File.WriteAllText(CALENDAROBJECT, Buffer)


    Und die Frage ist jetzt, WIE das Encoding bestimmt wird und vor allem WO Windows sich das merkt !

    Da muss es irgendein Regelwerk geben, dass sich meiner Kenntnis bisher entzieht ! :)

    LG
    Peter
    .Net verwendet defaultmässig utf8.
    Was ich verwunderlich finde, dasss WriteAllText scheints kein entsprechendes Bom generiert. Eiglich hätte ich gedacht, .Net tut das standardmässig.
    Und ohne Bom muss Notepad++ raten, und weil da sehr unübliche Zeichen drinne sind, tippt er wohl auf chinesisch.

    (So reime ich mir zusammen, was da passiert.)

    Schreib die Datei mal mit einem StreamWriter - der gibt dir mehr Steuerungs-Möglichkeiten an die hand - vlt. ist auch was dabei, womit du Bom-Generierung anschalten kannst.
    Dekompiliert man System.IO.File.WriteAllText(String, String) dann sieht man:

    C#-Quellcode

    1. public static void WriteAllText(string path, string contents)
    2. {
    3. if (path == null)
    4. {
    5. throw new ArgumentNullException("path");
    6. }
    7. if (path.Length == 0)
    8. {
    9. throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
    10. }
    11. File.InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM, true);
    12. }

    Also StreamWriter.UTF8NoBOM ist der Knackpunkt.

    Im Konstruktor von System.Text.Utf8Encoding kann man angeben, ob die BOM ausgegeben wird:

    VB.NET-Quellcode

    1. System.IO.File.WriteAllText("Test.txt", "Baum" & Convert.ToChar(0) & "Kuchen" & Convert.ToChar(255), New System.Text.Utf8Encoding(encoderShouldEmitUTF8Identifier:=False))


    @Peter329
    Es gibt übrigens noch bessere Möglichkeiten, Daten in Dateien zu schreiben. Deine Variante macht Probleme, wenn die Daten, die Du eigentlich abspeichern willst, eben diese 0- und 255-Zeichen beinhalten (ist wohl nicht sehr wahrscheinlich, aber dann sucht man sich dumm und dämlich).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Niko Ortner schrieb:

    wenn die Daten, die Du eigentlich abspeichern willst, eben diese 0- und 255-Zeichen beinhalten
    Jo: Public RECSEP As Char = Convert.ToChar(&HFF)
    @Peter329 Wenn Du allein Herr über diese Daten bist (Dein Programm schreibt, Dein Programm liest) könntest Du entweder diese Zeichen überhaupt ersetzen
    oder
    in der Datei übliche Zeichen nehmen, z.B. diese Zeichen durch einen sonst nicht vorkommenden markanten String ersetzen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    XML ist in VB übrigens äußerst bequem zu verwenden:

    VB.NET-Quellcode

    1. Dim Xml = <Calendar>
    2. <%= TextList.Select(Function(i) <TextEntry
    3. SaveDate=<%= saveDate.ToString %>
    4. Year=<%= i.entYear %>
    5. Text=<%= i.entText %>
    6. />) %>
    7. </Calendar>
    8. Xml.Save("EinfachNurDerPfad.xml")

    Hier muss dann auch kein Encoding angegeben werden, weil XElement (der Typ der Xml-Variable) selbst weiß, wie XML encodiert werden muss.
    Auslesen funktioniert fast genauso einfach:

    VB.NET-Quellcode

    1. Dim Xml = XElement.Load("EinfachNurDerPfad.xml")
    2. Dim TextEntries = Xml.<TextEntry>.Elements.Select(Function(i) New Ääähm With {.entYear = Integer.Parse(i.@Year), .entText = i.@Text})

    Ich bin mir nicht sicher, wo SaveDate hingehen soll und ob ToString für Datumse die richtige Herangehensweise ist. Zum Abspeichern verwendet man üblicherweise saveDate.ToBinary und zum Rausholen DateTime.FromBinary.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils