最近在写一个xml序列化及反序列化实现时碰到个问题,大致类似下面的代码:  

    class Program
{
static void Main1(string[] args)
{
var test = new Test() { A = "test" }; var ms = new MemoryStream();
using (XmlWriter xmlWriter = XmlWriter.Create(ms, new XmlWriterSettings() { Encoding = Encoding.UTF8, OmitXmlDeclaration = true }))//OmitXmlDeclaration表示是否需要xml申明头
{
XmlSerializer xz = new XmlSerializer(typeof(Test));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);//去掉xmlns属性
xz.Serialize(xmlWriter, test, ns); var xml = Encoding.UTF8.GetString(ms.ToArray());//得到xml
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);//报错:Data at the root level is invalid. Line 1, position 1.
}
}
}
public class Test
{
public string A { get; set; }
}

  上面代码序列化出来的那个xml变量值是:<Test><A>test</A></Test>,但是在XMLDocument.LoadXml(xml)方法报错:Data at the root level is invalid. Line 1, position 1.

  于是我将xml变量的值在调试状态下复制出来,接着在Main方法中写了下面的测试代码:   

    static void Main(string[] args)
{
string str1 = "<Test><A>test</A></Test>";
string str2 = "<Test><A>test</A></Test>";
Console.WriteLine("str1 == str2:" + (str1 == str2));//str1 == str2:False
Console.WriteLine("str1.Length=" + str1.Length);//str1.Length=24
Console.WriteLine("str2.Length=" + str2.Length);//str2.Length=25
Console.ReadKey();
}

  因为一直没遇到过这个问题,所以感觉很奇怪,然后查了一些资料,最后发现是UTF-8的BOM在作怪.

  什么是BOM?BOM的全称叫做" Byte Order Mark",UTF-8编码数据会在文件开头使用“EF BB BF”这三个字节表示BOM,而BOM的存在是为了区别字节序,存在BOM表示采用小端法,即低位在前边。

  对于UTF-8而言,因为它的编码单元就是字节,所以是没有字节序问题,但是UTF-16和UTF-32的编码单元分别是16-bit和32-bit,就对字节序要求了。

  比如,"\u4FA5"对应中文的“侥“,"\u5AF4"对应中文的“嫴“,如果两台不同的字节序的客户端A,B,A给B发送数据"\u4FA5",B可能就会认为是“嫴“,这就出错了。

  UTF-8虽然没有字节序问题,但为了兼容,UTF-8也会加上BOM。

  其实,如果注意一下,上面的例子中,str2的第一个字符是一个空字符,而不是<,而我们要解决UTF-8的BOM导致的数据问题时,只需要使用UTF8Encoding类传入false参数即可,例如上面的例子:  

    class Program
{
static void Main(string[] args)
{
var test = new Test() { A = "test" }; var ms = new MemoryStream();
using (XmlWriter xmlWriter = XmlWriter.Create(ms, new XmlWriterSettings() { Encoding = new UTF8Encoding(false), OmitXmlDeclaration = true }))//使用UTF8Encoding
{
XmlSerializer xz = new XmlSerializer(typeof(Test));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(string.Empty, string.Empty);//去掉xmlns属性
xz.Serialize(xmlWriter, test, ns); var xml = Encoding.UTF8.GetString(ms.ToArray());//得到xml,不含BOM
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);//不报错报错
}
}
}
public class Test
{
public string A { get; set; }
}

最新文章

  1. Java包装类
  2. Java Difference between Private and Protected
  3. Bzoj 1853: [Scoi2010]幸运数字 容斥原理,深搜
  4. cflow察看工程函数调用关系+Linux 0.11 内核实验环境
  5. 二分求解 三角形 stl的应用 涉及范围的二分查找可以先求上界再算下界,结果即上界减下界
  6. DRBD脑裂解决方法
  7. Break the Chocolate(规律)
  8. poj 2021 Relative Relatives(暴力)
  9. 基于Chrome开源提取的界面开发框架开篇--转
  10. CSS禁止输入之readonly VS disable
  11. Codeforces 623D [Amazing概率题]
  12. Struts2上传文件出错
  13. MongoDB 系列文章
  14. openssl命令行工具简介 - 指令x509
  15. [转]Peer-to-Peer Communication Across Network Address Translators
  16. .net加密web.config文件
  17. Extjs6 组件浅谈
  18. WPF 同一窗口内的多线程 UI(VisualTarget)
  19. poi操作word 2007 常用方法总结
  20. VMware安装linux系统报错:已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作。

热门文章

  1. mysql安装 报错解决
  2. numpy基础教程--浅拷贝和深拷贝
  3. 服务器安装Centos7
  4. Log4j漏洞源码分析
  5. typeScript基本概念
  6. [BUUCTF]REVERSE——helloword
  7. 项目管理的基本概念(Project)
  8. java 常用类库:BigInteger大整数;BigDecimal大小数(解决double精度损失);
  9. Tornado 之 WebSocket
  10. Centos7查看防火墙对应的开放端口以及进行端口操作