编写没有字节顺序标记 (BOM) 的文本文件?

Posted

技术标签:

【中文标题】编写没有字节顺序标记 (BOM) 的文本文件?【英文标题】:Write text files without Byte Order Mark (BOM)? 【发布时间】:2011-01-27 02:48:24 【问题描述】:

我正在尝试使用带有 UTF8 编码的 VB.Net 创建一个没有 BOM 的文本文件。任何人都可以帮助我,如何做到这一点? 我可以使用 UTF8 编码编写文件,但是,如何从中删除字节顺序标记?

编辑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

【问题讨论】:

如果你不想要BOM,你为什么要写GetPreamble()? 【参考方案1】:

为了省略字节顺序标记 (BOM),您的流必须使用 UTF8Encoding 的实例,而不是 System.Text.Encoding.UTF8(配置为生成 BOM)。有两种简单的方法可以做到这一点:

1.明确指定合适的编码:

    使用False 调用UTF8Encoding constructor 以获得encoderShouldEmitUTF8Identifier 参数。

    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。使用默认编码:

如果您根本不向StreamWriter 的构造函数提供Encoding,则StreamWriter 将默认使用不带BOM 的UTF8 编码,因此以下内容应该同样有效:

' 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。 My.Computer.FileSystem.WriteAllText 在这方面是个例外,也许是为了向后兼容 VB? File.WriteAllText 默认为 UFT8NoBOM。 如果您想为 VLC 编写 *.m3u8 播放列表文件,这将特别有用。 VLC 仍然无法使用 BOM 读取 UTF8 播放列表文件!这似乎是根据trac.videolan.org/vlc/ticket/21860 修复的,但只会包含在 VLC v4 中。【参考方案2】:

试试这个:

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

【讨论】:

【参考方案3】:

只需使用System.IO.File中的WriteAllText方法即可。

请查看File.WriteAllText的样本。

此方法使用不带字节顺序标记 (BOM) 的 UTF-8 编码,因此 使用 GetPreamble 方法将返回一个空字节数组。如果是 必须包含 UTF-8 标识符,例如字节顺序标记,在 文件的开头,使用 WriteAllText(String, String, Encoding) 方法重载,使用 UTF8 编码。

【讨论】:

My 命名空间中的那个确实使用了 BOM【参考方案4】:

对此的有趣说明:奇怪的是,System.IO.File 类的静态“CreateText()”方法创建 UTF-8 文件没有 BOM。

通常这是错误的来源,但在您的情况下,它可能是最简单的解决方法:)

【讨论】:

【参考方案5】:

如果您在创建新的StreamWriter 时未指定Encoding,则使用的默认Encoding 对象是UTF-8 No BOM,它是通过new UTF8Encoding(false, true) 创建的。

所以要创建一个不使用 BOM 的文本文件,使用不需要您提供编码的构造函数:

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

【讨论】:

如果我需要指定leaveOpen怎么办? @binki 在这种情况下,您不能使用StreamWriter 使用的默认编码。您需要为您的编码指定 new UTF8Encoding(false, true) 才能指定 leaveOpen 而没有 BOM。【参考方案6】:

我认为 Roman Nikitin 是对的。构造函数参数的含义被翻转。 False 表示没有 BOM,true 表示有 BOM。

您会获得 ANSI 编码,因为没有 BOM 且不包含非 ansi 字符的文件与 ANSI 文件完全相同。在“hi there”字符串中尝试一些特殊字符,您会看到 ANSI 编码更改为 without-BOM。

【讨论】:

【参考方案7】:

没有 BOM 的 XML 编码 UTF-8 我们需要将 XML 数据提交给 EPA,他们接受我们输入的应用程序需要没有 BOM 的 UTF-8。哦,是的,普通的 UTF-8 应该是每个人都可以接受的,但不是 EPA 可以接受的。这样做的答案在上面的 cmets 中。谢谢罗马尼基丁

这里是 XML 编码的 C# sn-p 代码:

    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),它将报告“Encode in ANSI”。我猜大多数文本编辑器都依靠 BOM 字符来判断它是否是 UTF-8。清楚地看到这一点的方法是使用像 WinHex (www.winhex.com) 这样的二进制工具。因为我正在寻找前后差异,所以我使用了 Microsoft WinDiff 应用程序。

【讨论】:

【参考方案8】:

对于 VB.Net Visual Basic,这是如何使其工作的:

My.Computer.FileSystem.WriteAllText("FileName", Data, False, System.Text.Encoding.ASCII)

【讨论】:

【参考方案9】:

您的输入文本可能包含字节顺序标记。在这种情况下,您应该在写入之前将其删除。

【讨论】:

请帮助我。如何在写入之前将其删除。 @user180326 默认阅读器不是已经为您过滤掉了吗?【参考方案10】:
Dim sWriter As IO.StreamWriter = New IO.StreamWriter(shareworklist & "\" & getfilename() & ".txt", False, Encoding.Default)

给你想要的结果(我认为)。

【讨论】:

在我的电脑上它会创建 ANSI 文件

以上是关于编写没有字节顺序标记 (BOM) 的文本文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 BOM 读取 UTF-8 文本文件

字节顺序标记——BOM,Byte Order Mark

BOM DOM

什么是BOM头(字节顺序标记(ByteOrderMark))

BOM

什么是文件的BOM头