最近在写一个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; }
}

C# UTF8的BOM导致XML序列化与反序列化报错:Data at the root level is invalid. Line 1, position 1.的更多相关文章

  1. C# LoadXml System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

    去掉BOM头 writer = new XmlTextWriter(stream, new UnicodeEncoding(false,false)); 如果是UTF8 writer = new Xm ...

  2. Windows phone 之XML序列化与反序列化

    为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...

  3. XmlSerializer 对象的Xml序列化和反序列化

    http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 这篇随笔对应的.Net命名空间是System.Xm ...

  4. C#的XML序列化及反序列化

    webservice在工作中用到的很多,基本都是以XML格式问通讯内容,其中最关键的就是XML串的序列化及反序列化. XML的运用中有两种信息传递,一种为XML的请求信息,另一种为返回信息,要运用XM ...

  5. .NET XML序列化与反序列化

    闲着没事,写了两个通用的XML序列化与反序列化的方法. 贴出来当作笔记吧! /// <summary> /// XML序列化 /// </summary> /// <ty ...

  6. XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置

    这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间.   为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中 ...

  7. C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化

    这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...

  8. C#实现接口xml序列化与反序列化

    C#实现接口xml序列化与反序列化   C#中接口无法被xml序列化,提示不支持.百度和bing也搜不到,只好自己动手写了 原理上肯定支持,.Net自己的xml序列化有一个IXmlSerializab ...

  9. xml序列化与反序列化工具

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

随机推荐

  1. CentOS 7.3安装完整开发环境

    系统版本CentOS 7.3(1611) 安装开发环境1) 通过group安装 yum groups mark install "Development Tools" yum gr ...

  2. final&static

    final 1.final修饰类,那么该类不能有子类,那么也就没有子类重写父类的方法,也就没有多态 2.final修饰成员变量,那么成员变量要么显式赋值(用第一种),要么在构造方法中赋值 无论哪一种, ...

  3. Output of C++ Program | Set 1

    Predict the output of below C++ programs. Question 1 1 // Assume that integers take 4 bytes. 2 #incl ...

  4. 【Linux】【Shell】【Basic】字符串操作

    1. 字符串切片:             ${var:offset:number}                 取字符串的子串:                 取字符趾的最右侧的几个字符:${ ...

  5. SpringBoot自定义控制层参数解析

    一.背景 在Spring的Controller中,我们通过@RequestParam或@RequestBody就可以将请求中的参数映射到控制层具体的参数中,那么这个是怎么实现的呢?如果我现在控制层中的 ...

  6. Airtest结合tidevice实现IOS自动化测试

    这篇博文内容,是基于之前的配置而来的.我们可以先回顾一下之前博文,Windows搭建mac黑苹果系统:WebDriverAgent重签名爬坑记 . 今天来分享下如何通过 tidevice实现IOS自动 ...

  7. macOS Monterey 12.1 (21C52) 正式版 ISO、IPSW、PKG 下载

    本站下载的 macOS Monterey 软件包,既可以拖拽到 Applications(应用程序)下直接安装,也可以制作启动 U 盘安装,或者在虚拟机中启动安装. 2021 年 12 月 14 日, ...

  8. 07- Vue3 UI Framework - Switch 组件

    为了更好的提升用户体验,我们这里再做一个很常用的开关组件 switch 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 switch 组件应分为选中/未被选中,两种状态 可以通过 ...

  9. useEffect无限调用问题

    1.useEfect()的基本用法 const [test,setTest] = useState(1) const init=()=>{ setTest(2) } useEffect(()=& ...

  10. eslint使用和配置

    1.全局安装 $ npm install -g eslint 2.初始化一个配置文件,得到一份文件名为 .eslintrc.js 的配置文件 eslint --init 3.配置.eslintrc.j ...