Viết tập tin văn bản mà không có Byte Order Mark (BOM)?


116

Tôi đang cố gắng tạo một tệp văn bản bằng VB.Net với mã hóa UTF8, không có BOM. Ai có thể giúp tôi, làm thế nào để làm điều này?
Tôi có thể viết tệp với mã hóa UTF8 nhưng, làm cách nào để xóa Byte Order Mark khỏi nó?

chỉnh sửa1: Tôi đã thử mã như thế này;

    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 được tạo chỉ với mã hóa UTF8 và 2.html được tạo với định dạng mã hóa ANSI.

Cách tiếp cận đơn giản - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html


8
Nếu bạn không muốn BOM, tại sao bạn lại viết GetPreamble ()?
Hans Passant

Câu trả lời:


200

Để bỏ qua dấu thứ tự byte (BOM), luồng của bạn phải sử dụng một thể hiện UTF8Encodingkhác với System.Text.Encoding.UTF8(được cấu hình để tạo BOM). Có hai cách dễ dàng để làm điều này:

1. Chỉ định rõ ràng một mã hóa phù hợp:

  1. Gọi UTF8Encodingconstructor với Falsecho encoderShouldEmitUTF8Identifiertham số.

  2. Truyền UTF8Encodingví dụ cho hàm tạo luồng.

' 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. Sử dụng mã hóa mặc định:

Nếu bạn hoàn toàn không cung cấp một Encodinghàm tạo cho StreamWriter, StreamWriterthì theo mặc định , sẽ sử dụng mã hóa UTF8 mà không có BOM, do đó, những điều sau đây cũng sẽ hoạt động tốt:

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

Cuối cùng, lưu ý rằng việc bỏ BOM chỉ được phép đối với UTF-8, không phải cho UTF-16.


Không phải lúc nào cũng khôn ngoan: ví dụ My.Computer.FileSystem.WriteAllTextviết BOM nếu không có mã hóa được chỉ định.
beppe9000

My.Computer.FileSystem.WriteAllTextcó phải là một ngoại lệ trong vấn đề này, có thể đoán khả năng tương thích VB ngược? File.WriteAllTextmặc định cho UFT8NoBOM.
jnm2

28

Thử cái này:

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

Chỉ cần sử dụng phương pháp WriteAllTexttừ System.IO.File.

Vui lòng kiểm tra mẫu từ File.WriteAllText .

Phương thức này sử dụng mã hóa UTF-8 mà không có Dấu thứ tự Byte (BOM), vì vậy sử dụng phương thức GetPreamble sẽ trả về một mảng byte trống. Nếu cần phải bao gồm một mã định danh UTF-8, chẳng hạn như dấu thứ tự byte, ở đầu tệp, hãy sử dụng quá tải phương thức WriteAllText (Chuỗi, Chuỗi, Mã hóa) với mã hóa UTF8.


Một từ không gian tên của tôi sử dụng BOM
beppe9000

4

Lưu ý thú vị liên quan đến điều này: thật kỳ lạ, phương thức "CreateText ()" tĩnh của lớp System.IO.File tạo các tệp UTF-8 mà không cần BOM.

Nói chung đây là nguồn của lỗi, nhưng trong trường hợp của bạn, nó có thể là cách giải quyết đơn giản nhất :)


4

Nếu bạn không chỉ định Encodingkhi tạo mới StreamWriter, Encodingđối tượng mặc định được sử dụng sẽ UTF-8 No BOMđược tạo thông qua new UTF8Encoding(false, true).

Vì vậy, để tạo tệp văn bản mà không cần sử dụng BOM của các hàm tạo không yêu cầu bạn cung cấp mã hóa:

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

Nếu tôi cần chỉ định leaveOpenthì sao?
binki

@binki trong trường hợp đó bạn không thể sử dụng mã hóa mặc định StreamWritersử dụng. Bạn sẽ cần chỉ định new UTF8Encoding(false, true)cho mã hóa của mình để có thể chỉ định leaveOpenvà không có BOM.
JG trong SD

3

Tôi nghĩ Roman Nikitin đã đúng. Ý nghĩa của đối số constructor được lật. Sai có nghĩa là không có BOM và phương tiện thực sự với BOM.

Bạn nhận được mã hóa ANSI vì một tệp không có BOM không chứa các ký tự không phải là ansi hoàn toàn giống với tệp ANSI. Hãy thử một số ký tự đặc biệt trong chuỗi "hi there" của bạn và bạn sẽ thấy mã hóa ANSI thay đổi thành không có BOM.


1

Mã hóa XML UTF-8 không có BOM
Chúng tôi cần gửi dữ liệu XML cho EPA và ứng dụng của họ nhận đầu vào của chúng tôi yêu cầu UTF-8 không có BOM. Ồ vâng, UTF-8 đơn giản nên được chấp nhận cho mọi người, nhưng không phải cho EPA. Câu trả lời để làm điều này là trong các ý kiến ​​trên. Cảm ơn Roman Nikitin .

Đây là đoạn mã C # cho mã hóa 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();  
    }    

Để xem nếu điều này thực sự loại bỏ ba ký tự đầu từ tệp đầu ra có thể gây hiểu nhầm. Ví dụ: nếu bạn sử dụng Notepad ++ (www.notepad-plus-plus.org), nó sẽ báo cáo Mã hóa mã hóa trong ANSI Hồi. Tôi đoán hầu hết các trình soạn thảo văn bản đang dựa vào các ký tự BOM để cho biết đó có phải là UTF-8 hay không. Cách để thấy rõ điều này là với một công cụ nhị phân như WinHex (www.winhex.com). Vì tôi đang tìm kiếm sự khác biệt trước và sau, tôi đã sử dụng ứng dụng Microsoft WinDiff .


-1

Nó có thể là văn bản đầu vào của bạn chứa một dấu thứ tự byte. Trong trường hợp đó, bạn nên loại bỏ nó trước khi viết.


1
Xin hãy giúp tôi. Làm thế nào để loại bỏ nó trước khi viết.
Vijay Balkawade

@ user180326 không phải trình đọc mặc định đã lọc ra cho bạn?
binki

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

Cung cấp cho bạn kết quả như những gì bạn muốn (tôi nghĩ).


1
Trên PC của tôi, nó tạo các tệp ANSI
Muflix 4/2/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.