如何在字符串比较中忽略UTF-8字节顺序标记?

Skr*_*rud 15 c# unit-testing equality utf-8 visual-studio-2010

我在使用Visual Studio 2010比较C#4.0中的单元测试中的字符串时遇到问题.同样的测试用例在Visual Studio 2008中正常工作(使用C#3.5).

这是相关的代码段:

byte[] rawData = GetData();
string data = Encoding.UTF8.GetString(rawData);

Assert.AreEqual("Constant", data, false, CultureInfo.InvariantCulture);
Run Code Online (Sandbox Code Playgroud)

在调试此测试时,该data字符串在肉眼看来包含与文字完全相同的字符串.当我打电话data.ToCharArray()时,我注意到该字符串的第一个字节data是价值65279这是UTF-8字节顺序标记.我不明白的是为什么要Encoding.UTF8.GetString()保持这个字节.

如何获取Encoding.UTF8.GetString()把字节顺序标记得到的字符串中?

更新:问题在于GetData(),它从磁盘读取文件,使用从文件中读取数据FileStream.readbytes().我通过使用a StreamReader并使用字符串将字符串转换为字节来纠正这个问题Encoding.UTF8.GetBytes(),这应该是它本来应该做的事情!谢谢你的帮助.

Jon*_*eet 16

好吧,我认为这是因为原始二进制数据包括BOM.您可以在解码后自己删除BOM,如果您不想要它 - 但您应该考虑字节数组是否应该考虑开始使用BOM.

编辑:或者,您可以使用a StreamReader来执行解码.这是一个示例,显示使用相同的字节数组转换为两个字符Encoding.GetString或通过以下方式转换为一个字符StreamReader:

using System;
using System.IO;
using System.Text;

class Test
{
    static void Main()
    {
        byte[] withBom = { 0xef, 0xbb, 0xbf, 0x41 };
        string viaEncoding = Encoding.UTF8.GetString(withBom);
        Console.WriteLine(viaEncoding.Length);

        string viaStreamReader;
        using (StreamReader reader = new StreamReader
               (new MemoryStream(withBom), Encoding.UTF8))
        {
            viaStreamReader = reader.ReadToEnd();           
        }
        Console.WriteLine(viaStreamReader.Length);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ter*_*ver 8

有一种比创建StreamReader和MemoryStream更有效的方法:

1)如果您知道总有BOM

string viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3);
Run Code Online (Sandbox Code Playgroud)

2)如果您不知道,请检查:

string viaEncoding;
if (withBom.Length >= 3 && withBom[0] == 0xEF && withBom[1] == 0xBB && withBom[2] == 0xBF)
    viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3);
else
    viaEncoding = Encoding.UTF8.GetString(withBom);
Run Code Online (Sandbox Code Playgroud)