如何在不添加字节顺序标记(BOM)的情况下编写文本文件?

121

我正在尝试使用VB.Net创建一个UTF8编码的文本文件,但不带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


8
如果你不想要BOM,为什么还要编写GetPreamble()函数? - Hans Passant
10个回答

211

为了省略字节顺序标记(BOM),您的流必须使用除System.Text.Encoding.UTF8之外的UTF8Encoding实例(该实例配置为生成BOM)。有两种简单的方法:

1、显式指定适当的编码:

  1. 调用带有 encoderShouldEmitUTF8Identifier 参数为 FalseUTF8Encoding 构造函数

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

如果您在 StreamWriter 的构造函数中没有提供 Encoding 参数,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默认使用UTF8NoBOM编码。 - jnm2
如果您想为VLC编写*.m3u8播放列表文件,这将非常有帮助。 VLC仍然无法读取带BOM的UTF8播放列表文件!根据https://trac.videolan.org/vlc/ticket/21860,这个问题似乎已经解决了,但只会在VLC v4中包含。 - PeterCo

29

试试这个:

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
只需简单地使用System.IO.File中的WriteAllText方法即可。
请查看File.WriteAllText的示例。
此方法使用UTF-8编码而不带有字节顺序标记(BOM),因此使用GetPreamble方法将返回一个空字节数组。如果需要在文件开头包含UTF-8标识符(如字节顺序标记),则可以使用带有UTF8编码的WriteAllText(String, String, Encoding)方法重载。

3
My命名空间中的这个文件确实使用BOM。 - beppe9000

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。 - JG in SD

4

关于这个有趣的注释:奇怪的是,System.IO.File类的静态“CreateText()”方法创建的UTF-8文件没有BOM。

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


3

我认为Roman Nikitin是正确的。构造函数参数的含义被颠倒了。False表示没有BOM,true表示有BOM。

如果一个不包含非ANSI字符且没有BOM的文件与一个ANSI文件完全相同,那么您将获得ANSI编码。尝试在“hi there”字符串中添加一些特殊字符,您会发现ANSI编码变为无BOM。


1
XML编码UTF-8无BOM
我们需要向EPA提交XML数据,他们的应用程序需要我们使用UTF-8无BOM格式。是的,对于其他人来说,纯UTF-8应该是可以接受的,但对于EPA来说不行。如何实现这一点在上面的评论中已经有了答案。感谢Roman Nikitin
这里是C#代码片段:
    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应用程序。

0

对于VB.Net Visual Basic,以下是使其工作的方法:

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

-1

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


1
请帮我。在写入之前如何删除它。 - VJOY
@user180326 默认的阅读器不是已经为你过滤掉了吗? - binki

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

给你想要的结果(我觉得)。


1
在我的电脑上,它创建 ANSI 文件。 - Muflix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接