当使用.net ASCIIEncoding类将字节数组解码为字符串时,我是否需要编写一些代码来检测和删除字节顺序标记,或者是否可以告诉ASCIIEncoding不要将字节顺序标记解码为字符串?
这是我的问题,当我这样做的时候:
string someString = System.Text.ASCIIEncoding.Default.GetString(someByteArray)someString将如下所示:
<?xml version="1.0"?>.......然后当我调用这个的时候:
XElement.Parse(someString)由于前三个字节引发异常: EF、BB、BF - UTF8字节顺序标记。所以我想,如果我指定UTF8编码,而不是缺省编码,就像这样:
System.Text.ASCIIEncoding.UTF8.GetString(someByteArray)ASCIIEncoding不会尝试将字节顺序标记解码为字符串。当我将返回的字符串复制到notepad++中时,可以看到?XML标记前面的字符。因此,现在字节顺序标记被解码为一个垃圾字符。在这种情况下,停止对字节顺序标记进行解码的最佳方法是什么?
发布于 2011-02-24 07:49:47
请不要使用
ASCIIEncoding.UTF8那真的只是
Encoding.UTF8它根本没有使用ASCIIEncoding。它只是在你的源代码中看起来很像。
从根本上说,问题是您的文件是UTF-8,而不是ASCII。这就是为什么它有一个UTF-8字节顺序标记。我强烈建议您使用Encoding.UTF8来读取UTF-8文件,不管用哪种方式。
如果您使用File.ReadAllText读取该文件,我怀疑它会自动删除该物料清单。或者,您可以在调用XElement.Parse之前对其进行修剪。使用错误的编码( ASCII或Encoding.Default)不是正确的方法。同样,它也不是一个垃圾字符。它是一个非常有用的字符,强烈地表明它确实是一个UTF-8文件--只是在这个特定的上下文中你不需要它。“垃圾”给人的印象是它是损坏的数据,不应该出现在文件中,但事实绝对不是这样的。
另一种方法是完全避免将其转换为文本。例如:
XElement element;
using (XmlReader reader = XmlReader.Create(new MemoryStream(bytes))
{
element = XElement.Load(reader);
}这样编码将被自动检测到。
发布于 2011-02-24 08:58:07
System.Text.Encoding.GetString()会保留物料清单(如果存在)并将其转换为UTF-16物料清单(U+FEFF)。把这看作是一个特性。严格地说,这是正确的做法,因为抛出BOM会使转换有损失,并且不能往返。然而,有些令人惊讶的是,他们没有提供一个标志来让你指定想要的行为,但你就是这样。所以...你有两个选择:
XElement.Parse()之前将其删除。或者...byte[]包装在MemoryStream中,将MemoryStream包装在StreamReader中,并使用XElement.Load()进行解析。你自己选吧。下面是一些可以工作的示例代码:
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 ;
}
}
}发布于 2011-02-24 08:00:03
这不是一个答案,但是注释中的代码是可怕的,在你的问题中加入这一点感觉有点粗鲁。你真的想这么做吗:
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"))));想知道为什么你会得到:
String length 3
String 'WD'
String 'feff,57,44'我当然是……
https://stackoverflow.com/questions/5098757
复制相似问题