Zapisywać pliki tekstowe bez znaku kolejności bajtów (BOM)?

116

Próbuję utworzyć plik tekstowy za pomocą VB.Net z kodowaniem UTF8, bez BOM. Czy ktoś może mi pomóc, jak to zrobić?
Mogę napisać plik z kodowaniem UTF8, ale jak usunąć z niego znacznik kolejności bajtów?

edit1: próbowałem kodu w ten sposób;

    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 zostanie utworzony tylko z kodowaniem UTF8, a 2.html zostanie utworzony z formatem kodowania ANSI.

Uproszczone podejście - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html

Vijay Balkawade
źródło
8
Jeśli nie chcesz BOM, dlaczego piszesz GetPreamble ()?
Hans Passant

Odpowiedzi:

200

Aby pominąć znacznik kolejności bajtów (BOM), strumień musi używać wystąpienia UTF8Encodinginnego niż System.Text.Encoding.UTF8(które jest skonfigurowane do generowania BOM). Można to zrobić na dwa proste sposoby:

1. Jawne określenie odpowiedniego kodowania:

  1. Wywołać UTF8Encodingkonstruktora z Falsedla encoderShouldEmitUTF8Identifierparametru.

  2. Przekaż UTF8Encodingwystąpienie do konstruktora strumienia.

' 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. Korzystanie z domyślnego kodowania:

Jeśli nie dostarczyć Encodingdo StreamWriter„s konstruktora w ogóle, StreamWriterbędzie domyślnie stosowania kodowania UTF8 bez BOM, więc dodaje powinien działać tak samo dobrze:

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

Na koniec należy zauważyć, że pominięcie BOM jest dopuszczalne tylko w przypadku UTF-8, a nie w przypadku UTF-16.

stakx - już nie wnoszący wkładu
źródło
Nie zawsze mądre: na przykład My.Computer.FileSystem.WriteAllTextzapisuje zestawienie komponentów, jeśli nie określono kodowania.
beppe9000
My.Computer.FileSystem.WriteAllTextjest wyjątkiem w tym względzie, zgadywanie może wstecznej kompatybilności VB? File.WriteAllTextdomyślnie UFT8NoBOM.
jnm2
28

Spróbuj tego:

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
Roman Nikitin
źródło
6

Po prostu użyj metody WriteAllTextz System.IO.File.

Sprawdź przykład z File.WriteAllText .

Ta metoda używa kodowania UTF-8 bez znacznika kolejności bajtów (BOM), więc użycie metody GetPreamble zwróci pustą tablicę bajtów. Jeśli konieczne jest uwzględnienie identyfikatora UTF-8, takiego jak znacznik kolejności bajtów, na początku pliku, użyj przeciążenia metody WriteAllText (String, String, Encoding) z kodowaniem UTF8.

Joe.wang
źródło
Ten z przestrzeni nazw My używa BOM
beppe9000
4

Interesująca uwaga w tym względzie: o dziwo, statyczna metoda „CreateText ()” klasy System.IO.File tworzy pliki UTF-8 bez BOM.

Ogólnie jest to źródło błędów, ale w twoim przypadku mogło to być najprostsze obejście :)

Tao
źródło
4

Jeśli nie określisz a Encodingpodczas tworzenia nowego, używany jest StreamWriterdomyślny Encodingobiekt UTF-8 No BOMutworzony za pośrednictwem new UTF8Encoding(false, true).

Aby utworzyć plik tekstowy bez użycia konstruktorów BOM, które nie wymagają kodowania:

new StreamWriter(Stream)
new StreamWriter(String)
new StreamWriter(String, Boolean)
JG w SD
źródło
A jeśli muszę to określić leaveOpen?
binki
@binki w takim przypadku nie możesz użyć domyślnego kodowania, które StreamWriterużywa. Musisz określić new UTF8Encoding(false, true)kodowanie, aby móc określić leaveOpeni nie mieć BOM.
JG w SD
3

Myślę, że Roman Nikitin ma rację. Znaczenie argumentu konstruktora jest odwracane. Fałsz oznacza brak BOM, a prawda oznacza BOM.

Otrzymujesz kodowanie ANSI, ponieważ plik bez BOM, który nie zawiera znaków innych niż ansi, jest dokładnie taki sam jak plik ANSI. Wypróbuj kilka znaków specjalnych w ciągu „cześć tam”, a zobaczysz zmianę kodowania ANSI na bez BOM.

jos
źródło
1

Kodowanie XML UTF-8 bez BOM
Musimy przesłać dane XML do EPA, a ich aplikacja, która przyjmuje nasze dane wejściowe, wymaga UTF-8 bez BOM. O tak, zwykły UTF-8 powinien być akceptowalny dla wszystkich, ale nie dla EPA. Odpowiedź na to znajduje się w powyższych komentarzach. Dziękuję Roman Nikitin .

Oto fragment kodu w języku C # do kodowania 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();  
    }    

Sprawdzanie, czy to faktycznie usuwa trzy wiodące znaki z pliku wyjściowego, może być mylące. Na przykład, jeśli używasz Notepad ++ (www.notepad-plus-plus.org), zgłosi „Encode in ANSI”. Wydaje mi się, że większość edytorów tekstu liczy na znaki BOM, aby stwierdzić, czy jest to UTF-8. Aby wyraźnie to zobaczyć, skorzystaj z narzędzia binarnego, takiego jak WinHex (www.winhex.com). Ponieważ szukałem różnicy przed i po, skorzystałem z aplikacji Microsoft WinDiff .

Jerry Banasik
źródło
-1

Możliwe, że tekst wejściowy zawiera znacznik kolejności bajtów. W takim przypadku należy go usunąć przed napisaniem.


źródło
1
Proszę, pomóż mi. Jak go usunąć przed napisaniem.
Vijay Balkawade
@ user180326 czy domyślny czytnik nie filtruje tego już za Ciebie?
binki
-1
Dim sWriter As IO.StreamWriter = New IO.StreamWriter(shareworklist & "\" & getfilename() & ".txt", False, Encoding.Default)

Daje wyniki, które chcesz (myślę).

Mwenyeji
źródło
1
Na moim komputerze tworzy pliki ANSI
Muflix