Textdateien ohne Byte Order Mark (BOM) schreiben?


116

Ich versuche, eine Textdatei mit VB.Net mit UTF8-Codierung ohne Stückliste zu erstellen. Kann mir jemand helfen, wie das geht?
Ich kann eine Datei mit UTF8-Codierung schreiben, aber wie entferne ich die Byte Order Mark daraus?

edit1: Ich habe Code wie diesen ausprobiert;

    Dim utf8 As New UTF8Encoding()
    Dim utf8EmitBOM As New UTF8Encoding(True)
    Dim strW As New StreamWriter("c:\temp\bom\1.html", True, utf8EmitBOM)
    strW.Write(utf8EmitBOM.GetPreamble())
    strW.WriteLine("hi there")
    strW.Close()

        Dim strw2 As New StreamWriter("c:\temp\bom\2.html", True, utf8)
        strw2.Write(utf8.GetPreamble())
        strw2.WriteLine("hi there")
        strw2.Close()

1.html wird nur mit UTF8-Codierung und 2.html mit ANSI-Codierungsformat erstellt.

Vereinfachter Ansatz - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html


8
Wenn Sie keine Stückliste möchten, warum schreiben Sie GetPreamble ()?
Hans Passant

Antworten:


200

Um das Byte Order Mark (BOM) wegzulassen, muss Ihr Stream eine UTF8Encodingandere Instanz als System.Text.Encoding.UTF8(die zum Generieren einer Stückliste konfiguriert ist) verwenden. Es gibt zwei einfache Möglichkeiten, dies zu tun:

1. Explizite Angabe einer geeigneten Codierung:

  1. Rufen Sie den UTF8EncodingKonstruktor mit Falsefür den encoderShouldEmitUTF8IdentifierParameter auf.

  2. Übergeben Sie die UTF8EncodingInstanz an den Stream-Konstruktor.

' VB.NET:
Dim utf8WithoutBom As New System.Text.UTF8Encoding(False)
Using sink As New StreamWriter("Foobar.txt", False, utf8WithoutBom)
    sink.WriteLine("...")
End Using
// C#:
var utf8WithoutBom = new System.Text.UTF8Encoding(false);
using (var sink = new StreamWriter("Foobar.txt", false, utf8WithoutBom))
{
    sink.WriteLine("...");
}

2. Verwenden Sie die Standardcodierung:

Wenn Sie überhaupt keinen Konstruktor von Encodingto angeben StreamWriter, StreamWriterwird standardmäßig eine UTF8-Codierung ohne Stückliste verwendet. Daher sollte Folgendes genauso gut funktionieren:

' VB.NET:
Using sink As New StreamWriter("Foobar.txt")
    sink.WriteLine("...")
End Using
// C#:
using (var sink = new StreamWriter("Foobar.txt"))
{
    sink.WriteLine("...");
}

Beachten Sie schließlich, dass das Weglassen der Stückliste nur für UTF-8 und nicht für UTF-16 zulässig ist.


Nicht immer klug: My.Computer.FileSystem.WriteAllTextSchreibt beispielsweise die Stückliste, wenn keine Codierung angegeben ist.
beppe9000

My.Computer.FileSystem.WriteAllTextist diesbezüglich eine Ausnahme, die möglicherweise auf Abwärts-VB-Kompatibilität hindeutet? File.WriteAllTextDer Standardwert ist UFT8NoBOM.
jnm2

28

Versuche dies:

Encoding outputEnc = new UTF8Encoding(false); // create encoding with no BOM
TextWriter file = new StreamWriter(filePath, false, outputEnc); // open file with encoding
// write data here
file.Close(); // save and close it

6

Verwenden Sie einfach die Methode WriteAllTextvon System.IO.File.

Bitte überprüfen Sie das Beispiel aus File.WriteAllText .

Diese Methode verwendet die UTF-8-Codierung ohne Byte-Order Mark (BOM). Bei Verwendung der GetPreamble-Methode wird daher ein leeres Byte-Array zurückgegeben. Wenn am Anfang einer Datei eine UTF-8-Kennung, z. B. eine Bytereihenfolge, eingefügt werden muss, verwenden Sie die WriteAllText-Methodenüberladung (String, String, Encoding) mit UTF8-Codierung.


Der aus dem My-Namespace verwendet BOM
beppe9000

4

Interessanter Hinweis dazu: Seltsamerweise erstellt die statische Methode "CreateText ()" der System.IO.File-Klasse UTF-8-Dateien ohne Stückliste.

Im Allgemeinen ist dies die Quelle von Fehlern, aber in Ihrem Fall könnte es die einfachste Problemumgehung gewesen sein :)


4

Wenn Sie Encodingbeim Erstellen eines neuen Objekts kein angeben , wird StreamWriterstandardmäßig das EncodingObjekt verwendet, über UTF-8 No BOMdas erstellt wird new UTF8Encoding(false, true).

So erstellen Sie eine Textdatei ohne Stücklistenverwendung der Konstruktoren, für die Sie keine Codierung angeben müssen:

new StreamWriter(Stream)
new StreamWriter(String)
new StreamWriter(String, Boolean)

Was ist, wenn ich angeben muss leaveOpen?
Binki

@binki In diesem Fall können Sie die verwendete Standardcodierung nicht StreamWriterverwenden. Sie müssen angeben, new UTF8Encoding(false, true)damit Ihre Codierung leaveOpendie Stückliste angeben kann und nicht.
JG in SD

3

Ich denke, Roman Nikitin hat recht. Die Bedeutung des Konstruktorarguments wird umgedreht. Falsch bedeutet keine Stückliste und wahr bedeutet mit Stückliste.

Sie erhalten eine ANSI-Codierung, da eine Datei ohne Stückliste, die keine Nicht-Ansi-Zeichen enthält, genau mit einer ANSI-Datei identisch ist. Probieren Sie einige Sonderzeichen in Ihrer "Hallo" -String aus, und Sie werden sehen, wie sich die ANSI-Codierung in "Ohne Stückliste" ändert.


1

XML-Codierung UTF-8 ohne Stückliste
Wir müssen XML-Daten an die EPA senden, und für ihre Anwendung, die unsere Eingaben übernimmt, ist UTF-8 ohne Stückliste erforderlich. Oh ja, einfaches UTF-8 sollte für alle akzeptabel sein, aber nicht für die EPA. Die Antwort darauf finden Sie in den obigen Kommentaren. Vielen Dank, dass Sie Roman Nikitin .

Hier ist ein C # -Schnipsel des Codes für die XML-Codierung:

    Encoding utf8noBOM = new UTF8Encoding(false);  
    XmlWriterSettings settings = new XmlWriterSettings();  
    settings.Encoding = utf8noBOM;  
          
    using (XmlWriter xw = XmlWriter.Create(filePath, settings))  
    {  
        xDoc.WriteTo(xw);  
        xw.Flush();  
    }    

Es kann irreführend sein, zu sehen, ob dadurch tatsächlich die drei führenden Zeichen aus der Ausgabedatei entfernt werden. Wenn Sie beispielsweise Notepad ++ (www.notepad-plus-plus.org) verwenden, wird "In ANSI verschlüsseln" gemeldet. Ich denke, die meisten Texteditoren zählen auf die Stücklistenzeichen, um festzustellen, ob es sich um UTF-8 handelt. Dies lässt sich mit einem Binärwerkzeug wie WinHex (www.winhex.com) klar erkennen . Da ich nach einem Vorher- Nachher- Unterschied gesucht habe, habe ich die Microsoft WinDiff- Anwendung verwendet.


-1

Möglicherweise enthält Ihr Eingabetext eine Bytereihenfolge. In diesem Fall sollten Sie es vor dem Schreiben entfernen.


1
Bitte helfen Sie mir. So entfernen Sie es vor dem Schreiben.
Vijay Balkawade

@ user180326 filtert der Standardleser das nicht schon für Sie heraus?
Binki

-1
Dim sWriter As IO.StreamWriter = New IO.StreamWriter(shareworklist & "\" & getfilename() & ".txt", False, Encoding.Default)

Gibt Ihnen Ergebnisse als die, die Sie wollen (ich denke).


1
Auf meinem PC erstellt es ANSI-Dateien
Muflix
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.