如何检测.NET StreamReader在基础流中找到UTF8 BOM?

22

我使用FileStream(filename,FileMode.Open,FileAccess.Read,FileShare.ReadWrite)来获取一个流,然后使用StreamReader(stream,true)

有没有办法检查流是否以UTF8 BOM开头? 我注意到没有BOM的文件被StreamReader读取时会变成UTF8.

如何区分它们?

3个回答

17

与硬编码字节相比,使用API更加美观。

public string ConvertFromUtf8(byte[] bytes)
{
  var enc = new UTF8Encoding(true);
  var preamble = enc.GetPreamble();
  if (preamble.Where((p, i) => p != bytes[i]).Any()) 
    throw new ArgumentException("Not utf8-BOM");
  return enc.GetString(bytes.Skip(preamble.Length).ToArray());
}

1
@carlo-v-dango,我建议添加一些空值检查,因为如果文件为空,则字节可能为空。if (preamble.Where((p, i) => bytes.Length > i && p != bytes[i]).Any()) 或者任何你喜欢的方式。 - Martin

9
你可以通过使用无BOM的UTF8编码初始化StreamReader,并在第一次读取后检查CurrentEncoding是否发生变化来检测StreamReader是否遇到了BOM。
var utf8NoBom = new UTF8Encoding(false);
using (var reader = new StreamReader(file, utf8NoBom))
{
    reader.Read();
    if (Equals(reader.CurrentEncoding, utf8NoBom))
    {
        Console.WriteLine("No BOM");
    }
    else
    {
        Console.WriteLine("BOM detected");
    }
}

我从未想过这会奏效。谢谢!可惜相反的情况不成立。你不能传递int UTF8Encoding(true),并期望它返回UTF8Encoding(false)。 - Cameron Taggart

8

这能帮到您吗?您需要检查文件的前三个字节:

    public static void Main(string[] args)
    {
        FileStream fs = new FileStream("spork.txt", FileMode.Open);
        byte[] bits = new byte[3];
        fs.Read(bits, 0, 3);

        // UTF8 byte order mark is: 0xEF,0xBB,0xBF
        if (bits[0] == 0xEF && bits[1] == 0xBB && bits[2] == 0xBF)
        {

        }

        Console.ReadLine();
    }
}

3
请确保将FileStream放入using语句中,因为它是一个可丢弃的对象。 - aolszowka
传统上,最好使用前导而不是硬编码字节值。 - Suncat2000

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