Écrire des fichiers texte sans marque d'ordre d'octet (BOM)?


116

J'essaie de créer un fichier texte en utilisant VB.Net avec encodage UTF8, sans BOM. Quelqu'un peut-il m'aider, comment faire cela?
Je peux écrire un fichier avec un encodage UTF8 mais, comment en supprimer Byte Order Mark?

edit1: j'ai essayé un code comme celui-ci;

    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 est créé avec le codage UTF8 uniquement et 2.html est créé avec le format de codage ANSI.

Approche simplifiée - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html


8
Si vous ne voulez pas de nomenclature, pourquoi écrivez-vous GetPreamble ()?
Hans Passant

Réponses:


200

Afin d'omettre la marque d'ordre d'octet (BOM), votre flux doit utiliser une instance de UTF8Encodingautre que System.Text.Encoding.UTF8(qui est configurée pour générer une nomenclature). Il existe deux façons simples de procéder:

1. Spécification explicite d'un codage approprié:

  1. Appelez le UTF8Encodingconstructeur avec Falsepour le encoderShouldEmitUTF8Identifierparamètre.

  2. Passez l' UTF8Encodinginstance au constructeur de flux.

' 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. En utilisant le codage par défaut:

Si vous ne fournissez pas du tout un constructeur de Encodingto StreamWriter, StreamWriterutilisera par défaut un encodage UTF8 sans BOM, donc ce qui suit devrait fonctionner aussi bien:

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

Enfin, notez que l'omission de la nomenclature n'est autorisée que pour UTF-8, pas pour UTF-16.


Pas toujours judicieux: par exemple, My.Computer.FileSystem.WriteAllTextécrit la nomenclature si aucun codage n'est spécifié.
beppe9000 le

My.Computer.FileSystem.WriteAllTextest une exception à cet égard, devinant peut-être la compatibilité VB vers l'arrière? File.WriteAllTextpar défaut, UFT8NoBOM.
jnm2

28

Essaye ça:

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

Utilisez simplement la méthode WriteAllTextde System.IO.File.

Veuillez vérifier l'exemple de File.WriteAllText .

Cette méthode utilise le codage UTF-8 sans marque d'ordre d'octet (BOM), donc l'utilisation de la méthode GetPreamble renverra un tableau d'octets vide. S'il est nécessaire d'inclure un identificateur UTF-8, tel qu'une marque d'ordre d'octet, au début d'un fichier, utilisez la surcharge de méthode WriteAllText (String, String, Encoding) avec le codage UTF8.


Celui de mon espace de noms utilise la nomenclature
beppe9000

4

Note intéressante à ce sujet: étrangement, la méthode statique "CreateText ()" de la classe System.IO.File crée des fichiers UTF-8 sans BOM.

En général, c'est la source de bogues, mais dans votre cas, cela aurait pu être la solution de contournement la plus simple :)


4

Si vous ne spécifiez pas de Encodinglors de la création d'un nouvel objet, l'objet StreamWriterpar défaut Encodingutilisé est celui UTF-8 No BOMqui est créé via new UTF8Encoding(false, true).

Donc, pour créer un fichier texte sans la nomenclature, utilisez des constructeurs qui ne vous obligent pas à fournir un encodage:

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

Et si je dois préciser leaveOpen?
binki

@binki dans ce cas, vous ne pouvez pas utiliser le codage par défaut qui StreamWriterutilise. Vous devrez spécifier new UTF8Encoding(false, true)votre encodage pour pouvoir spécifier leaveOpenet ne pas avoir la nomenclature.
JG en SD

3

Je pense que Roman Nikitin a raison. La signification de l'argument constructeur est inversée. Faux signifie pas de nomenclature et vrai signifie avec nomenclature.

Vous obtenez un codage ANSI car un fichier sans nomenclature qui ne contient pas de caractères non ansi est exactement le même qu'un fichier ANSI. Essayez quelques caractères spéciaux dans votre chaîne "hi there" et vous verrez le codage ANSI passer à sans BOM.


1

Codage XML UTF-8 sans BOM
Nous devons soumettre des données XML à l'EPA et leur application qui prend notre entrée nécessite UTF-8 sans BOM. Oh oui, l'UTF-8 devrait être acceptable pour tout le monde, mais pas pour l'EPA. La réponse à cela se trouve dans les commentaires ci-dessus. Merci Roman Nikitin .

Voici un extrait C # du code pour l'encodage XML:

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

Voir si cela supprime réellement les trois premiers caractères du fichier de sortie peut être trompeur. Par exemple, si vous utilisez Notepad ++ (www.notepad-plus-plus.org), il indiquera «Encode in ANSI». Je suppose que la plupart des éditeurs de texte comptent sur les caractères de la nomenclature pour dire s'il s'agit de UTF-8. La manière de voir clairement ceci est avec un outil binaire comme WinHex (www.winhex.com). Comme je cherchais une différence avant et après, j'ai utilisé l' application Microsoft WinDiff .


-1

Il se peut que votre texte d'entrée contienne une marque d'ordre d'octet. Dans ce cas, vous devez le supprimer avant d'écrire.


1
Veuillez m'aider. Comment le supprimer avant d'écrire.
Vijay Balkawade

@ user180326 Le lecteur par défaut ne filtre-t-il pas déjà cela pour vous?
binki

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

Vous donne des résultats comme ceux que vous voulez (je pense).


1
Sur mon PC, il crée des fichiers ANSI
Muflix
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.