在.NET中,我试图使用Encoding.UTF8.GetString
方法,该方法需要一个字节数组并将其转换为string
。Encoding.UTF8.GetString没有考虑到前导码/ BOM
看起来这种方法忽略了BOM (Byte Order Mark),它可能是UTF8字符串的合法二进制表示的一部分,并将其作为字符使用。
我知道我可以根据需要使用TextReader
消化物料清单,但我认为GetString方法应该是某种使我们的代码更短的宏。
我错过了什么吗?这是故意的吗?
这里是一个再现代码:
static void Main(string[] args)
{
string s1 = "abc";
byte[] abcWithBom;
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms, new UTF8Encoding(true)))
{
sw.Write(s1);
sw.Flush();
abcWithBom = ms.ToArray();
Console.WriteLine(FormatArray(abcWithBom)); // ef, bb, bf, 61, 62, 63
}
byte[] abcWithoutBom;
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms, new UTF8Encoding(false)))
{
sw.Write(s1);
sw.Flush();
abcWithoutBom = ms.ToArray();
Console.WriteLine(FormatArray(abcWithoutBom)); // 61, 62, 63
}
var restore1 = Encoding.UTF8.GetString(abcWithoutBom);
Console.WriteLine(restore1.Length); // 3
Console.WriteLine(restore1); // abc
var restore2 = Encoding.UTF8.GetString(abcWithBom);
Console.WriteLine(restore2.Length); // 4 (!)
Console.WriteLine(restore2); // ?abc
}
private static string FormatArray(byte[] bytes1)
{
return string.Join(", ", from b in bytes1 select b.ToString("x"));
}
我明白了。感谢您的澄清! – 2012-07-28 13:59:59
@RonKlein此外,您可以说'restore2 = restore2.TrimStart('\ uFEFF')'删除前导BOM字符。我也一度想知道为什么'(new UTF8Encoding(true)).getBytes(“abc”)'和'(new UTF8Encoding(false))。GetBytes(“abc”)'产生相同的输出,现在知道,'GetBytes'并不假定你在文件的开头,所以它从不使用'GetPreamble'。如果你使用'GetBytes'或者'GetString',你必须显式地声明'GetPreamble',或者明确地跳过前导码。 – 2012-07-29 12:45:57