希望论坛网络学院作者家园流水日志 使用XmlSerializer序列化反序列化对象(生产xml文件)

1  /  1  页   1 跳转 查看:770

使用XmlSerializer序列化反序列化对象(生产xml文件)

使用XmlSerializer序列化反序列化对象(生产xml文件)

public class o2xml
    {
        public class MyObject //定义一个内部类MyObject
        {
            public int a;
            public int b;
            public string c;
        }        void doit()
        {
            MyObject myObj = new MyObject();
            myObj.a = 1;//为对象赋值
            myObj.b = 2;
            myObj.c = "===";
            //序列化
            XmlSerializer serilizer = new XmlSerializer(typeof(MyObject));
            StringBuilder sbXML = new StringBuilder();
            System.IO.StringWriter writer = new System.IO.StringWriter(sbXML);
            serilizer.Serialize(writer, myObj);
            writer.Close();
            Console.WriteLine(sbXML.ToString());
            //反序列化
            StringReader reader = new StringReader(sbXML.ToString());
            System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(MyObject));
            MyObject newBoku = (MyObject)xs.Deserialize(reader);
            reader.Close();
            Console.WriteLine(newBoku.a + " " + newBoku.b + " " + newBoku.c);
            Console.Read();
        }       
        static void Main(String[] args)
        {
            new o2xml().doit();
        }
    }
}

也可以通过System.IO.StreamWriter和System.IO.StreamReader来操作。只是这时要使用文件路径:
System.IO.StreamWriter writer = new System.IO.StreamWriter(filePath)
System.IO.StreamReader reader = new System.IO.StreamReader(filePath)
输出结果为:
<?xml version="1.0" encoding="utf-16"?>
<MyObject xmlnssi="http://www.w3.org/2001/XMLSchema-instance" xmlnssd="http://www.w3.org/2001/XMLSchema">
  <a>1</a>
  <b>2</b>
  <c>===</c>
</MyObject>
1 2 ===

多多实践吧!
 

回复:使用XmlSerializer序列化反序列化对象(生产xml文件)

Net 中的序列化与反序列化    一、概述
    当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。
    把对象转换为字节序列的过程称为对象的序列化。
    把字节序列恢复为对象的过程称为对象的反序列化。

    二、对象的序列化主要有两种用途:
    1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
    我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁 盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基 本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
  2) 在网络上传送对象的字节序列。
  对象仅在创建对象的应用程序域中有效。除非对象是从MarshalByRefObject派生得到或标记为 Serializable,否则,任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如果对象标记为 Serializable,则该对象将被自动序列化,并从一个应用程序域传输至另一个应用程序域,然后进行反序列化,从而在第二个应用程序域中产生出该对象的一个精确副本。此过程通常称为按值封送。如果对象是从MarshalByRefObject派生得到,则从一个应用程序域传递至另一个应用程序域的是对象引用,而不是对象本身。也可以将从MarshalByRefObject派生得到的对象标记为Serializable。远程使用此对象时,负责进行序列化并已预先配置为SurrogateSelector的格式化程序将控制序列化过程,并用一个代理替换所有从MarshalByRefObject派生得到的对象。如果没有预先配置为SurrogateSelector,序列化体系结构将遵从下面的标准序列化规则.

    三、.NET提供了三种序列化方式
    [1]、XML Serializer
    [2]、SOAP Serializer
    [3]、BinarySerializer

    四、基本序列化
    要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记,如下所示:
    [Serializable]
    public class MyObject
    {
        public int n1 = 0;
        public int n2 = 0;
        public String str = null;
    }
  [BinarySerializer]
    将此类的一个实例序列化为一个文件: 
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "一些字符串";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();

    反序列化:

IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open,
FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(fromStream);
stream.Close();

  [XMLSerializer]
    将此类的实例序列化成一个Xml文件.

XmlSerializer ser = new XmlSerializer(obj.GetType());
ser.Serialize(new FileStream(@"users.xml", FileMode.Create), obj);

    反序列化:

XmlSerializer serializer = new XmlSerializer(Type.GetType("MyObject"));
MyObject my=(MyObject)serializer.Deserialize(new FileStream(@"users.xml",FileMode.Open));

    说明:使用二进制格式化程序进行序列化。您只需创建一个要使用的流和格式化程序的实例,然后调用格式化程序的 Serialize 方法。流和要序列化的对象实例作为参数提供给此调用。类中的所有成员变量(甚至标记为 private 的变量)都将被序列化,但这一点在本例中未明确体现出来。在这一点上,二进制序列化不同于只序列化公共字段的 XML 序列化程序。将对象还原到它以前的状态也非常容易。首先,创建格式化程序和流以进行读取,然后让格式化程序对对象进行反序列化。   
    [SOAP Serializer]
    如果要求具有可移植性,请使用 SoapFormatter。所要做的更改只是将以上代码中的BinaryFormatter换 SoapFormatter,而 Serialize 和 Deserialize 调用不变。
 

回复:使用XmlSerializer序列化反序列化对象(生产xml文件)

.net提供的序列化和反序列化,只是简化类型转化操作而提供的方便,并不代表效率很高。

现在发现另外一个问题了,当我把20M的文件分成10个2M的文件来读的时候,速度明显比直接读20M的文件要快多了。按我的理解,读10个2M的文件,读完后还需要将文件内容合并起来,按理讲速度应该还要慢才对啊,但实际它却比读一个整个的文件速度要快。 
   
  所以我觉得C#下这样读大文件肯定有个地方有影响速度的瓶劲,但我不知道这个问题出在哪里?该如何解决? 
   
  我读的文件为我用序列化写进去的内容,写文件的代码如下: 
  ArrayList  list  =  getList(); 
  System.IO.FileStream  fis  =  new  System.IO.FileStream(pathName+"\\"+fileName,  FileMode.Create,FileAccess.Write,FileShare.None,4096); 
   
  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter  format  =  new  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
                          format.Serialize(fis,  wgoList); 
   
  fis.Close();
 

回复:使用XmlSerializer序列化反序列化对象(生产xml文件)

本来就已经是读文件夹中的很多文件了,其中的文件有大有小了,稍大的点文件再拆分开来会导致程序麻烦很多了,我现在就想弄明白一下C#反序列化的原理,是哪些因素在影响它的速度,郁闷,找来找去都没找到这方面的资料 
   
  另外,我做了一个测试,如果我只是写一个ArrayList进文件,而这个arrayList里全是string,这样一个文件即使是50M,也只要2秒左右的时间就读出来了。但是我的程序应用中,一个15M的文件(里面的对象是自己的类,有很多个),居然要读出差不多20秒的时间出来。 
  我现在就是弄不明白是什么导致了二者之间的差异的
 

回复:使用XmlSerializer序列化反序列化对象(生产xml文件)

看来你对  C#  序列化和反序列化使用不存在问题 
  问题是你的需求有点儿变态——20M,也太大了吧 
   
  原因是  .NET  默认提供的序列化/反序列化实现并不是针对你这样的变态需求优化的,呵呵 
  好比刷油漆的故事:蘸一蘸油漆桶,然后一路刷下去,越刷越远,每蘸一次油漆桶所化的时间越来越长... 
  好比大量的  string  +  string  的操作的优化方案是使用  StringBuilder——它就是为此而优化的 
   
  那么,对于你的情况而言,同理:可能你要编写自己的序列化/反序列化实现了 
   
  楼上给你提供的两篇文章不知道针对你的需求是否合适,但至少实在不行你可以参考文章以及代码自己实现并优化。 
   
  另外,你提到的  ArrayList  中存放  string  很序列化/反序列化很快,一个原因是  string  比较简单,另外一个原因是不是你的  ArrayList  中存放了不同的类的实例(异质结构)? 
  还有,从某种程度上而言,尽量使用类型化的数据结构,例如  MyObject[]  会比  ArrayList  效率更高——少了大量的  box/unbox  操作,也许能为你的优化提供一定的参考。 
   
  针对油漆桶的故事,可以考虑拆分成多个数组来序列化/反序列化,效率会高一些。或者深入分析你的代码中,找到导致油漆桶事件发生的原因来优化。

近来一直忙,最近才试完了那些另外的序列化的方法 
   
  速度虽是比C#本身自己的序列化快了一点,不过还是没有什么明显的改善。看了些他们的代码基本明白序列化和反序列化的过程,同样是转成字节流,再经过多层次的解析,速度当然是慢了 
   
  最终我还是放弃了用序列化存储数据了,还是自己定义一个文件格式来读起来的快

http://www.codeproject.com/cs/library/AltSerializer.asp 
  http://www.codeproject.com/csharp/simpleserializer.asp 
  就搜Serializer行了。
 
1  /  1  页   1 跳转

版权所有 希望论坛  希望网络 流水日志 八方学院 理想论坛 86802  Sitemap

Powered by Discuz!NT 2.0.1214    Copyright © 2009 08119.
Processed in 0.34375 second(s) , 15 queries.
返顶部