Scrivere file di testo senza Byte Order Mark (BOM)?


116

Sto cercando di creare un file di testo utilizzando VB.Net con codifica UTF8, senza BOM. Qualcuno può aiutarmi, come farlo?
Posso scrivere file con codifica UTF8 ma, come rimuovere Byte Order Mark da esso?

edit1: ho provato un codice come questo;

    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 viene creato solo con la codifica UTF8 e 2.html viene creato con il formato di codifica ANSI.

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


8
Se non vuoi un BOM, perché stai scrivendo GetPreamble ()?
Hans Passant

Risposte:


200

Per omettere il byte order mark (BOM), il flusso deve utilizzare un'istanza di UTF8Encodingdiverso da System.Text.Encoding.UTF8(configurato per generare una BOM). Ci sono due semplici modi per farlo:

1. Specificare esplicitamente una codifica adatta:

  1. Chiama il UTF8Encodingcostruttore con Falseper il encoderShouldEmitUTF8Identifierparametro.

  2. Passa l' UTF8Encodingistanza al costruttore del flusso.

' 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. Utilizzando la codifica predefinita:

Se non si fornisce un Encodinga StreamWriter's costruttore a tutti, StreamWritersarà per difetto di uso di una codifica UTF-8 senza BOM, quindi il seguente dovrebbe funzionare altrettanto bene:

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

Infine, si noti che l'omissione della distinta componenti è consentita solo per UTF-8, non per UTF-16.


Non sempre saggio: ad esempio My.Computer.FileSystem.WriteAllTextscrive la distinta base se non viene specificata alcuna codifica.
beppe9000

My.Computer.FileSystem.WriteAllTextè un'eccezione a questo proposito, forse indovinare per la compatibilità con VB all'indietro? File.WriteAllTextil valore predefinito è UFT8NoBOM.
jnm2

28

Prova questo:

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

Basta semplicemente usare il metodo WriteAllTextda System.IO.File.

Si prega di controllare l'esempio da File.WriteAllText .

Questo metodo usa la codifica UTF-8 senza un Byte-Order Mark (BOM), quindi l'uso del metodo GetPreamble restituirà una matrice di byte vuota. Se è necessario includere un identificatore UTF-8, ad esempio un contrassegno dell'ordine dei byte, all'inizio di un file, utilizzare l'overload del metodo WriteAllText (String, String, Encoding) con codifica UTF8.


Quello dal mio spazio dei nomi usa BOM
beppe9000

4

Nota interessante al riguardo: stranamente, il metodo statico "CreateText ()" della classe System.IO.File crea file UTF-8 senza BOM.

In generale questa è la fonte dei bug, ma nel tuo caso avrebbe potuto essere la soluzione più semplice :)


4

Se non si specifica un Encodingquando si crea un nuovo oggetto StreamWriterpredefinito Encodingutilizzato UTF-8 No BOMè quello creato tramite new UTF8Encoding(false, true).

Quindi per creare un file di testo senza l'uso della distinta componenti dei costruttori che non richiedono di fornire una codifica:

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

E se ho bisogno di specificare leaveOpen?
Binki

@binki in quel caso non puoi usare la codifica predefinita che StreamWriterusa. Dovrai specificare new UTF8Encoding(false, true)affinché la tua codifica sia in grado di specificare leaveOpene non avere la distinta componenti.
JG in SD

3

Penso che Roman Nikitin abbia ragione. Il significato dell'argomento del costruttore è capovolto. Falso significa niente BOM e true significa BOM.

Si ottiene una codifica ANSI perché un file senza una distinta materiali che non contiene caratteri non ansi è esattamente uguale a un file ANSI. Prova alcuni caratteri speciali nella stringa "ciao là" e vedrai che la codifica ANSI cambia in senza BOM.


1

Codifica XML UTF-8 senza BOM
Dobbiamo inviare dati XML all'EPA e la loro applicazione che accetta il nostro input richiede UTF-8 senza BOM. Oh sì, il semplice UTF-8 dovrebbe essere accettabile per tutti, ma non per l'EPA. La risposta a questa operazione è nei commenti sopra. Grazie Roman Nikitin .

Di seguito è riportato un frammento C # del codice per la codifica XML: Here is a C # snippet of the code for the XML encoding:

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

Per vedere se questo rimuove effettivamente i tre caratteri iniziali dal file di output può essere fuorviante. Ad esempio, se utilizzi Notepad ++ (www.notepad-plus-plus.org), riporterà "Encode in ANSI". Immagino che la maggior parte degli editor di testo stia contando sui caratteri BOM per sapere se è UTF-8. Il modo per vederlo chiaramente è con uno strumento binario come WinHex (www.winhex.com). Poiché stavo cercando una differenza prima e dopo, ho usato l' applicazione Microsoft WinDiff .


-1

È possibile che il testo di input contenga un contrassegno per l'ordine dei byte. In tal caso, dovresti rimuoverlo prima di scrivere.


1
Per favore aiutami. Come rimuoverlo prima di scrivere.
Vijay Balkawade

@ user180326 il lettore predefinito non lo filtra già per te?
binki

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

Ti dà risultati come quelli che desideri (credo).


1
Sul mio PC crea file ANSI
Muflix
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.