เขียนไฟล์ข้อความโดยไม่มี Byte Order Mark (BOM)?


116

ฉันกำลังพยายามสร้างไฟล์ข้อความโดยใช้ VB.Net ด้วยการเข้ารหัส UTF8 โดยไม่มี BOM ใครสามารถช่วยฉันทำอย่างไร
ฉันสามารถเขียนไฟล์ด้วยการเข้ารหัส UTF8 แต่จะลบ Byte Order Mark ออกจากไฟล์ได้อย่างไร

แก้ไข 1: ฉันได้ลองใช้รหัสแบบนี้แล้ว

    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 สร้างด้วยการเข้ารหัส UTF8 เท่านั้นและ 2.html สร้างด้วยรูปแบบการเข้ารหัส ANSI

แนวทางที่เรียบง่าย - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html


8
ถ้าคุณไม่ต้องการ BOM ทำไมคุณถึงเขียน GetPreamble ()?
Hans Passant

คำตอบ:


200

ในการละเว้นเครื่องหมายลำดับไบต์ (BOM) สตรีมของคุณต้องใช้อินสแตนซ์UTF8Encodingอื่นที่ไม่ใช่System.Text.Encoding.UTF8(ซึ่งกำหนดค่าให้สร้าง BOM) มีสองวิธีง่ายๆในการดำเนินการนี้:

1. ระบุการเข้ารหัสที่เหมาะสมอย่างชัดเจน:

  1. เรียกตัวUTF8Encodingสร้างด้วยFalseสำหรับencoderShouldEmitUTF8Identifierพารามิเตอร์

  2. ส่งUTF8Encodingอินสแตนซ์ไปยังตัวสร้างสตรีม

' 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. ใช้การเข้ารหัสเริ่มต้น:

หากคุณไม่จัดหาตัวสร้างEncodingให้กับStreamWriterเลยStreamWriterโดยค่าเริ่มต้นจะใช้การเข้ารหัส UTF8 โดยไม่มี BOM ดังนั้นสิ่งต่อไปนี้ควรใช้งานได้เช่นกัน:

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

สุดท้ายโปรดทราบว่าการละเว้น BOM จะอนุญาตเฉพาะ UTF-8 เท่านั้นไม่ใช่สำหรับ UTF-16


ไม่ฉลาดเสมอไปตัวอย่างเช่นMy.Computer.FileSystem.WriteAllTextเขียน BOM หากไม่มีการระบุการเข้ารหัส
beppe9000

My.Computer.FileSystem.WriteAllTextเป็นข้อยกเว้นในเรื่องนี้การคาดเดาความเข้ากันได้ของ VB แบบย้อนกลับอาจจะ? File.WriteAllTextค่าเริ่มต้นเป็น UFT8NoBOM
jnm2


6

เพียงแค่ใช้วิธีการจากWriteAllTextSystem.IO.File

กรุณาตรวจสอบตัวอย่างจากFile.WriteAllText

วิธีนี้ใช้การเข้ารหัส UTF-8 โดยไม่มี Byte-Order Mark (BOM) ดังนั้นการใช้เมธอด GetPreamble จะส่งคืนอาร์เรย์ไบต์ว่าง หากจำเป็นต้องใส่ตัวระบุ UTF-8 เช่นเครื่องหมายลำดับไบต์ที่จุดเริ่มต้นของไฟล์ให้ใช้เมธอด WriteAllText (String, String, Encoding) โอเวอร์โหลดด้วยการเข้ารหัส UTF8


หนึ่งจากเนมสเปซของฉันใช้ BOM
beppe9000

4

หมายเหตุที่น่าสนใจเกี่ยวกับสิ่งนี้: น่าแปลกที่เมธอด "CreateText ()" แบบคงที่ของคลาส System.IO.File จะสร้างไฟล์ UTF-8 โดยไม่มี BOM

โดยทั่วไปนี่คือแหล่งที่มาของจุดบกพร่อง แต่ในกรณีของคุณอาจเป็นวิธีแก้ปัญหาที่ง่ายที่สุด :)


4

หากคุณไม่ได้ระบุEncodingเมื่อสร้างอ็อบเจ็กต์StreamWriterเริ่มต้นใหม่ที่Encodingใช้คือUTF-8 No BOMสิ่งที่สร้างผ่านnew UTF8Encoding(false, true).

ดังนั้นในการสร้างไฟล์ข้อความโดยไม่ต้องใช้ BOM ของตัวสร้างที่ไม่ต้องการให้คุณทำการเข้ารหัส:

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

ถ้าต้องระบุต้องทำleaveOpenอย่างไร?
binki

@binki ในกรณีนั้นคุณไม่สามารถใช้การเข้ารหัสเริ่มต้นที่StreamWriterใช้. คุณจะต้องระบุnew UTF8Encoding(false, true)การเข้ารหัสของคุณเพื่อให้สามารถระบุleaveOpenและไม่มี BOM
JG ใน SD

3

ฉันคิดว่า Roman Nikitin พูดถูก ความหมายของอาร์กิวเมนต์ตัวสร้างถูกพลิก เท็จหมายถึงไม่มี BOM และวิธีการที่แท้จริงกับ BOM

คุณได้รับการเข้ารหัส ANSI เนื่องจากไฟล์ที่ไม่มี BOM ที่ไม่มีอักขระที่ไม่ใช่ ansi เหมือนกับไฟล์ ANSI ทุกประการ ลองใช้อักขระพิเศษในสตริง "hi there" ของคุณแล้วคุณจะเห็นการเข้ารหัส ANSI เปลี่ยนเป็นไม่มี BOM


1

การเข้ารหัส XML UTF-8 โดยไม่มี BOM
เราจำเป็นต้องส่งข้อมูล XML ไปยัง EPA และแอปพลิเคชันที่รับข้อมูลเข้าของเราต้องใช้ UTF-8 โดยไม่มี BOM ใช่ UTF-8 ธรรมดาควรเป็นที่ยอมรับสำหรับทุกคน แต่ไม่ใช่สำหรับ EPA คำตอบสำหรับการทำเช่นนี้อยู่ในความคิดเห็นด้านบน ขอบคุณโรมัน Nikitin

นี่คือตัวอย่าง C # ของรหัสสำหรับการเข้ารหัส 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();  
    }    

หากต้องการดูว่าการลบอักขระนำหน้าสามตัวออกจากไฟล์เอาต์พุตนั้นอาจทำให้เข้าใจผิดได้หรือไม่ ตัวอย่างเช่นหากคุณใช้Notepad ++ (www.notepad-plus-plus.org) ระบบจะรายงาน "เข้ารหัสใน ANSI" ฉันเดาว่าโปรแกรมแก้ไขข้อความส่วนใหญ่จะใช้อักขระ BOM เพื่อบอกว่าเป็น UTF-8 หรือไม่ วิธีที่จะเห็นสิ่งนี้อย่างชัดเจนคือการใช้เครื่องมือไบนารีเช่นWinHex (www.winhex.com) เนื่องจากฉันกำลังมองหาความแตกต่างก่อนและหลังฉันจึงใช้แอปพลิเคชันMicrosoft WinDiff


-1

อาจเป็นไปได้ว่าข้อความที่คุณป้อนมีเครื่องหมายลำดับไบต์ ในกรณีนั้นคุณควรลบออกก่อนเขียน


1
โปรดช่วยฉันด้วย วิธีลบก่อนเขียน
Vijay Balkawade

@ user180326 เครื่องอ่านเริ่มต้นไม่ได้กรองสิ่งนั้นให้คุณแล้วหรือ
binki

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

ให้ผลลัพธ์ตามที่คุณต้องการ (ฉันคิดว่า)


1
บนพีซีของฉันมันสร้างไฟล์ ANSI
Muflix
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.