How to tell ASCIIEncoding class not to decode the byte order mark
使用.NET asciiEncoding类将字节数组解码为字符串时,是否需要编写一些代码来检测和删除字节顺序标记,或者是否可以告诉asciiEncoding不要将字节顺序标记解码为字符串?
这是我的问题,当我这样做的时候:
1 | string someString = System.Text.ASCIIEncoding.Default.GetString(someByteArray) |
一些字符串将如下所示:
1 | ???<?xml version="1.0"?>....... |
然后当我称之为:
1 | XElement.Parse(someString) |
前三个字节引发异常:ef bb bf-utf8字节顺序标记。所以我认为,如果我指定utf8编码,而不是默认编码,比如:
1 | System.Text.ASCIIEncoding.UTF8.GetString(someByteArray) |
AsciiEncoding不会尝试将字节顺序标记解码为字符串。当我将返回的字符串复制到记事本++中时,我可以看到一个?XML标记前面的字符。所以现在字节顺序标记被解码成一个垃圾字符。在这种情况下,停止解码字节顺序标记的最佳方法是什么?
请不要使用
1 | ASCIIEncoding.UTF8 |
那真的只是
1 | Encoding.UTF8 |
它根本不使用
从根本上说,问题在于您的文件是UTF-8,而不是ASCII。这就是为什么它有一个UTF-8字节顺序标记。我强烈建议您使用
如果你用
另一种方法是完全避免将其转换为文本。例如:
1 2 3 4 5 | XElement element; using (XmlReader reader = XmlReader.Create(new MemoryStream(bytes)) { element = XElement.Load(reader); } |
这样就可以自动检测编码。
转换为字符串,在对该字符串调用
将
你的选择。下面是一些适用的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | using System.IO; using System.Text; using System.Xml.Linq; namespace TestDrive { class Program { public static void Main() { byte[] octets = File.ReadAllBytes("utf8-encoded-document-with-BOM.xml" ) ; // ----------------------------------------------- // option 1: use a memory stream and stream reader // ----------------------------------------------- using ( MemoryStream ms = new MemoryStream( octets) ) using ( StreamReader sr = new StreamReader( ms , Encoding.UTF8 , true ) ) { XElement element1 = XElement.Load( sr ) ; } // -------------------------------------------------------------------- // option 2: convert to string, then look for and remove BOM if present // // The .Net framework Encoding.GetString() methods preserve the BOM if // it is present. Since the internal format of .Net string is UTF-16, // the BOM is converted to the UTF-16 encoding (U+FEFF). // // Consider this a feature. // -------------------------------------------------------------------- // convert to UTF-16 string string xml = Encoding.UTF8.GetString( octets ) ; // Two different ways of getting the BOM //string UTF16_BOM = Encoding.Unicode.GetString(Encoding.Unicode.GetPreamble()).ToCharArray() ; const string UTF16_BOM ="\uFEFF" ; // parse the element, removing the BOM if we see it. XElement element2 = XElement.Parse( xml.StartsWith( UTF16_BOM ) ? xml.Substring(1) : xml ) ; return ; } } } |
这不是一个答案,但是评论中的代码是可怕的,把它放在你的问题中感觉有点粗鲁。你真的想这么做吗?
1 2 3 4 5 | Byte[] bytes = new byte [] { 0xEF,0xBB,0xBF, 0x57, 0x44 }; String txt = Encoding.UTF8.GetString(bytes); Console.WriteLine("String length {0}", txt.Length); Console.WriteLine("String '{0}'", txt); Console.WriteLine("Chars '{0}'", String.Join(",", txt.Select(chr => ((int)chr).ToString("x2")))); |
想知道你为什么得到:
1 2 3 | String length 3 String 'WD' String 'feff,57,44' |
我当然是…