Encoding eines Files bestimmen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Encoding eines Files bestimmen

    Ich versuche die alten My. Methoden durch moderne Konstrukte zu ersetzen.

    VB.NET-Quellcode

    1. 'Write message to file
    2. 'My.Computer.FileSystem.WriteAllText(strObject, fileText, True)
    3. File.AppendAllText(strObject, fileText)


    Die auskommentierte Anweisung hat Text-Files problemlos fortgesetzt.

    Mit AppendAllText klappt das nicht mehr. Die Daten werden zwar angehängt, aber neu hinzugefügten Daten sind nicht lesbar, da der Zeichensatz verstrubbelt ist.

    Mit einem Hexeditor kann ich folgendes sehen: Die Datei ist im Unicode Format UTF-16 gespeichert, also zwei Bytes für ein Zeichen. Die neuen Daten werden aber in ASCII Format angehängt, d.h. ein Byte pro Zeichen. Das führt zu den nichtlesebaren Zeichen.

    Nun hab ich gesehen, dass die AppendAllText Methode eine Überlagerung hat, bei der man als dritten Parameter das Encoding mitgeben kann.

    Die Frage ist nun: wie mache ich das? Wie kann ich das Encoding der Datei extrahieren und wie ist das dann beim Schreiben zu setzen. Das Ganze soll möglichst mit beliebigen Dateien funktionieren.

    Oder geht das ganz anders?

    ErfinderDesRades schrieb:

    nur beim Lesen ermitteln
    Nö.
    Das Encoding ist in einer Textdatei implizit nicht abgelegt, das muss der Überbringer explizit dazu sagen oder in der 1. Zeile steht die CodePage.
    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!
    Herzlichen Dank an die Ratgeber. Die Routine habe ich damit jetzt hinbekommen.

    VB.NET-Quellcode

    1. 'Get file encoding
    2. Dim FileEncoding As Encoding
    3. Try
    4. Dim r = New StreamReader(strObject, Encoding.Default)
    5. Dim strBuffer As String = r.ReadToEnd()
    6. FileEncoding = r.CurrentEncoding
    7. r.Close()
    8. Catch ex As FileNotFoundException
    9. FileEncoding = Encoding.Default
    10. Catch ex As Exception
    11. MsgBox(strObject & ":" & vbCrLf & ex.Message)
    12. Exit Sub
    13. End Try


    Wenn eine BOM enthalten ist, dann wird das Encoding zurückgegeben. Wenn keine BOM enthalten ist, wird, "Encoding.Default" ausgegeben. Wenn die Datei nicht existiert, dann wird "Encoding.Default" gesetzt.

    Das hab ich alles mit meinem kleinen Hexeditor geprüft und damit ist mein Problem erst mal gelöst.

    Ein bissl stört mich noch, dass zum Ermitteln der BOM der GESAMTE File gelesen wird. Dabei würde es doch genügen, nur die ersten drei Bytes zu lesen! Ich hab mir schon "Read" bzw. "ReadBlock" angesehen aber irgendwie scheinen mir diese Methoden für das Problem nicht so recht geeignet.

    Kann man das Lesen der Datei einschränken?
    Dann will ich mal ein artiger Schüler sein und deinen Rat mit dem Object Explorer befolgen (s. Anhang) :D

    Die einzigen beiden Read Methoden die "String" zurückliefern, sind das bereits bekannte "ReadToEnd" und "ReadLine". Beides scheint mir nicht geeignet.

    Also ich seh nix was mir weiterhelfen würde ... :(
    Bilder
    • StreamReader.jpg

      364,39 kB, 1.522×1.010, 184 mal angesehen
    die Read-Methoden brauchen garnix zurückgeben - es ist also ganz egal, welche du nimmst.
    Es ist ein NebenEffekt jeglicher Read-Methode, dass dabei das CurrentEncoding des StreamReaders aus dem BOM gelesen wird - falls vorhanden.

    Das kannst du daran erkennen, dass du das CurrentEncoding mal vor dem ersten Read-Aufruf nachguckst, und dann danach.

    nur .ReadToEnd ist natürlich Overkill.

    ErfinderDesRades schrieb:

    Es ist ein NebenEffekt jeglicher Read-Methode, dass dabei das CurrentEncoding des StreamReaders aus dem BOM gelesen wird - falls vorhanden.


    Das muss man natürlich wissen. :D

    VB.NET-Quellcode

    1. 'Dummy READ to get BOM (Byte Order Mask)
    2. Dim intFirstByte As Integer = r.Read()


    So klappt das jetzt! Supi! Herzlichen Dank, mein Problem ist zufriedenstellend gelöst.