C# UTF8的BOM导致XML序列化与反序列化报错:Data at the root level is invalid. Line 1, position 1.
最近在写一个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.的更多相关文章
- 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 ...
- Windows phone 之XML序列化与反序列化
为什么要做序列化和反序列化? 一个回答: 我们都知道对象是不能在网络中直接传输的,不过还有补救的办法.XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储 ...
- XmlSerializer 对象的Xml序列化和反序列化
http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html 这篇随笔对应的.Net命名空间是System.Xm ...
- C#的XML序列化及反序列化
webservice在工作中用到的很多,基本都是以XML格式问通讯内容,其中最关键的就是XML串的序列化及反序列化. XML的运用中有两种信息传递,一种为XML的请求信息,另一种为返回信息,要运用XM ...
- .NET XML序列化与反序列化
闲着没事,写了两个通用的XML序列化与反序列化的方法. 贴出来当作笔记吧! /// <summary> /// XML序列化 /// </summary> /// <ty ...
- XmlSerializer 对象的Xml序列化和反序列化,XMLROOT别名设置
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中 ...
- C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化
这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...
- C#实现接口xml序列化与反序列化
C#实现接口xml序列化与反序列化 C#中接口无法被xml序列化,提示不支持.百度和bing也搜不到,只好自己动手写了 原理上肯定支持,.Net自己的xml序列化有一个IXmlSerializab ...
- xml序列化与反序列化工具
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
随机推荐
- What all is inherited from parent class in C++?
派生类可以从基类中继承: (1)基类中定义的每个数据成员(尽管这些数据成员在派生类中不一定可以被访问): (2)基类中的每个普通成员函数(尽管这些成员函数在派生类中不一定可以被访问): (3)The ...
- Linux基础命令---smbpasswd管理samba密码
smbpasswd smbpasswd指令可以用来修改samba用户的的密码,该指令不仅可以修改本地samba服务器的用户密码,还可以修改远程samba服务器的用户密码. 此命令的适用范围:RedHa ...
- 什么是maven(一)
转自博主--一杯凉茶 我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就是为了帮助那些和我一样对于m ...
- python实现skywalking的trace模块过滤和报警
skywalking本身的报警功能,用起来视乎不是特别好用,目前想实现对skywalking的trace中的错误接口进行过滤并报警通知管理员和开发.所以自己就用python对skywalking做了二 ...
- SQL 基础知识终极指南
什么是数据库? 数据库是以电子方式从系统中存储和检索的大量数据集合. 存储在数据库中的结构化数据被处理.操纵.控制和更新以执行各种操作. 行业中使用的一些流行数据库是 Oracle.MySQL.Pos ...
- ThreadLocal的使用方法
ThreadLocal的使用方法 (2011-10-10 22:05:48) 转载▼ 概述 ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个 ...
- ubuntu 10.04安装和配置Samba
1. 安装samba服务器 sudo apt-get install samba //主程序包 sudo apt-get install smbfs //文件下载挂载工具 2. 创建共享目录 mk ...
- win10 linux ubuntu子系统 使用adb
条件 本文已经默认你已经在win10系统下成功配置了ubuntu子系统,所以唯一的条件就是windows上的adb 版本和ubuntu子系统的adb版本一致. 方法 怎么来保证adb 版本一致呢?在本 ...
- CF808A Lucky Year 题解
Content 年份中有不超过 \(1\) 个非 \(0\) 数字的年份是幸运年份.现给出当前年份 \(n\),求到下一个幸运年份还要等多久. 数据范围:\(1\leqslant n\leqslant ...
- LuoguP2097 资料分发1 题解
Content 有一些电脑,一部分电脑有双向数据线连接.如果一个电脑得到数据,它可以传送到的电脑都可以得到数据.现在,你有这个数据,问你至少将其输入几台电脑,才能使所有电脑得到数据. 数据范围:\(n ...