System.IO 二

 

 

 接着上篇的来  System.IO  

 

  FileSystemWatcher

 

 

   指向这个签名的方法

 

  可以监听目录发生了什么事件

 

 

 

 

 

例如:

  static void Main(string[] args)
        {
            Console.WriteLine("请开始你的表演:");
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"E:\Test";  //此目录一定需要存在,不然会引发 ArgumentException 异常
            //设置需要 留意 的事情
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            //只观察文本文件
            watcher.Filter = "*.txt"; 
            //添加事件处理程序
            watcher.Changed += new FileSystemEventHandler(Onchange);
            watcher.Created += new FileSystemEventHandler(Onchange);
            watcher.Deleted += new FileSystemEventHandler(Onchange);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);
            //开始观察目录
            watcher.EnableRaisingEvents = true;
            //等待用户退出程序
            Console.WriteLine("请按 `q` 退出程序");
            while (Console.Read() !='q');          
        }
        static void Onchange(object source, FileSystemEventArgs e) 
        {
            //指定当文件改变、创建或者删除的时候需要做的事情
            Console.WriteLine("File:{0} {1}",e.FullPath,e.ChangeType);
        }
        static void OnRenamed(object source, RenamedEventArgs e) 
        {
            //指定当文件重命名的时候需要做的事情
            Console.WriteLine("File: {0} renamed to {1}",e.OldFullPath,e.FullPath);
        }

 

 

 对象序列化

     序列化描述了持久化一个对象的状态到流(如文件流和内存流)的过程。序列化服务保存应用程序数据相对于IO命名空间的读读取器/编写器,减少了很多的麻烦。

在看列子之前,你先要理解一个类。

 [Serializable]  //序列化的对象需要标记为可以序列化
    public class UserProp 
    {
        public string WindowColor;
        public int FontSize;
    }



  Console.WriteLine("请开始你的表演:");
            UserProp userData = new UserProp();
            userData.WindowColor = "red";
            userData.FontSize = 50;

            //将一个对象保存到一个本地
            BinaryFormatter binFormat = new BinaryFormatter();
            using (Stream fStrem=new FileStream("Haha.txt", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                binFormat.Serialize(fStrem,userData); //将对象序列化为流
            }
            Console.ReadLine();

  虽然对象序列化保存对象非常简单,单幕后的调用过程非常复杂。除了保存为二进制格式外还可以保存为简单对象访问协议(SOAP)或XML格式。

最后要知道对象图可以持久化为任意的System.IO.Stream派生类型。

  一组关联对象(包括基类和派生类)被总称为一个对象图。对象图提供一种很简明的方式来记载一组对象如何相互引用对方。

 

为序列化配置对象

   为每个一个关联 的类(或结构)加上 [serializable] 特性,不参与到序列化配置中,可以在这么域前面加上 [NoSerialized]特性。

 

定义可序列化对象

 [Serializable]
    public class Radio 
    {
        public bool hasTweeters;
        public bool hasSubWoofers;

        [NonSerialized]   //把此变量设置为不可序列化的
        public string radioID = "X-Y110";
    }

    [Serializable]
    public class Car 
    {
        public Radio theRadio = new Radio();
        public bool isHatchBack;
    }

    [Serializable]
    public class JamesBondCar : Car 
    {
        public bool canFly;
        public bool canSubmerge;
    }

注:[Serializable]特性不能被继承。因此,如果从被标记为[Serializable]的类派生一个类,子类也必须被标记为[Serializable],否则它不能持久化。

 

有一句话叫做公共的属性,私有的字段

  一般的情况,是在一个类中,我们把字段定义为私有的,属性则定义为公共的。这句的来源则是我们在一个类中声明一个字段,然后把这个字段进行重构,封装字段。

 

    [Serializable]
    public class Person
    {
        //公共字段
        public bool isAlive = true;

        //私有字段
        private int personAge = 21;

       //公共属性,私有字段
        private string fName;
        public string FName
        {
            get { return fName; }
            set { fName = value; }
        }

 

我们使用 BinaryFormatter或 SoapFormatter进行处理,都可以保存到所选的流中。然而,XmLSerializer不会保存personAge的值。

 

序列化格式方法

    一旦将类型配置为参与.NET序列化,接下来就是选择当持久化对象图时使用哪种格式(二进制、SOAP或XML),有以下3中选择:

BinaryFormatter:

SoapFormatter:

XmlSerializer:

在引用不出命名空间的时候请去引用里面添加引用。

第一个上面说过了,是二进制格式。

 

这里我们可以了解下它的属性和方法,主要是序列化和反序列化的方法。SOAP是一个标准的XML格式。

 

 

有很的重载构造函数。

下面会介绍如何使用这三种格式序列化对象。

这三个都市直接派生于System.Object.

 

IFormatter和IremotingFormatting接口

 

我们来看看IFormatter接口

 

它们两个类继承同一个接口,而此接口中这两个主要的方法刚好符合我们的要求 。所有我们建立一个方法使用这两个类中的一个来序列化一个对象图。

/// <summary>
        /// 两个类的通用方法
        /// </summary>
        /// <param name="itfFormat">BinaryFormatter或SoapFormatter的实例</param>
        /// <param name="destStrem">准备的Stream流</param>
        /// <param name="graph">需要写的序列化对象</param>
        static void SerializeObjectGraph(IFormatter itfFormat, Stream destStrem, object graph) 
        {
            itfFormat.Serialize(destStrem,graph);
        }

 

 在格式化程序中的类型保真

       在3种格式化程序中,最明显不同是对象图被持久化为不同的流(二进制、SOAP或XML)的方式。BinaryFormatter在希望用值(例如以一个完整的副本)跨越.NET应用程序机器边界传递对象时成为理想的选择。当希望尽可能延伸持久化对象图的使用范围时,SoapFormatter和XmlSerializer是理想选择。

 

 

①使用BinaryFormatter序列化对象

  Ⅰ Serialize():将一个对象图按字节顺序转化为一个对象图。

  Ⅱ Deserialize():讲一个持久化的字节顺序转化为一个对象图。

        static void Main(string[] args)
        {
            Console.WriteLine("请开始你的表演:");

            JamesBondCar jbc = new JamesBondCar();
            jbc.canFly = true;
            jbc.canSubmerge = false;
            jbc.theRadio.stationPresets = new double[] { 89.3, 105.1, 97.1 };
            jbc.theRadio.hasTweeters = true;

            //以二进制格式保存car
            SaveAsBinaryFormat(jbc,"CarDara.dat");

            Console.ReadLine();

        }
        static void SaveAsBinaryFormat(object objGraph, string fileName)
        {
            BinaryFormatter binFormat = new BinaryFormatter();
            using (Stream fStream=new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.None))
            {
                binFormat.Serialize(fStream, objGraph);
            }
            Console.WriteLine("保存成功了");
        }

 

 使用BinaryFormatter反序列化对象,SOAP和XML反序列化类似

  /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="fileName">文件名</param>
        static void LoadFormBinaryFile(string fileName)
        {
            BinaryFormatter binFormat = new BinaryFormatter();
            using (Stream fStream=File.OpenRead(fileName))
            {
                JamesBondCar carFormDisk =(JamesBondCar)binFormat.Deserialize(fStream); //Deserialize返回的是object类型,转下型然后接收就可以了
                Console.WriteLine("fly属性:{0}",carFormDisk.canFly);
            }
        }

 

②使用SoapFprmatter序列化对象

    static void SaveAsSoapFormat(object objGraph,string fileName) 
        {
            SoapFormatter soapFomat = new SoapFormatter();
            using (Stream fStream=new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.None))
            {
                soapFomat.Serialize(fStream,objGraph);
            }
            Console.WriteLine("保存Soap格式成功");
        }

 

③使用XmlSerializer序列化对象   

   static void SaveAsXmlFormat(object objGraph, string fileName) 
        {
            //此类的构成函数必须给参数,需要确定你对谁进行序列化
            XmlSerializer xmlFormat = new XmlSerializer(typeof(JamesBondCar));
            using (Stream fStream=new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.None))
            {
                xmlFormat.Serialize(fStream,objGraph);    
            }
            Console.WriteLine("序列化XML完成");
        }

 XmlSerializer要求对象图中的所有序列化类型支持默认的构造函数。没有的话需要加上

上面三种可以看出,XML格式是最清楚和简单的。

 

控制生成的XML数据

       System.Xml.Serialization命名空间中的部分特性

      

    

    

    

例如:

 

如果想更深一点的了解可以去官网查看

 

 序列化对象集合

   前面已经演示了如何将一个对象持久化为一个流,下面演示如何保存一组对象。

         一组对象就需要用到集合了。(数组、ArrayList或List<T>)。用数组代替我们之前用的单个对象就可以了

 

   List<JamesBondCar> myCars = new List<JamesBondCar>()
            {
                new JamesBondCar(){ canFly=true, canSubmerge=false, isHatchBack=false},
                new JamesBondCar(){ canFly=true, canSubmerge=true, isHatchBack=false},
                new JamesBondCar(){ canFly=true, canSubmerge=false, isHatchBack=true},
            };

            //以二进制格式保存car
            // SaveAsBinaryFormat(jbc, "CarDara.dat");
           // LoadFormBinaryFile("CarDara.dat");
           //SaveAsSoapFormat(jbc,"CarData.soap");
            SaveAsXmlFormat(myCars,"CarData.xml");
            Console.ReadLine();
        static void SaveAsXmlFormat(List<JamesBondCar> objGraph, string fileName) 
        {
            //此类的构成函数必须给参数,需要确定你对谁进行序列化
            XmlSerializer xmlFormat = new XmlSerializer(typeof(List<JamesBondCar>));
            using (Stream fStream=new FileStream(fileName,FileMode.Create,FileAccess.Write,FileShare.None))
            {
                xmlFormat.Serialize(fStream,objGraph);    
            }
            Console.WriteLine("序列化XML完成");
        }

另外两个类似。

 

自定义Soap/Binary序列化过程

      System.Runtime.Serizlization命名空间核心类型

 

 

 

深入了解对象序列化

   当BinaryFormatter序列化一个对象图时,它负责传送下面的信息到指定的流。

  ①在对象图中对象的完全限定名(如 MyApp.Car)

  ②定义对象图的程序名称(如 MyApp.exe)

  ③SerizlizationInfo 类的一个实例,包含了所有由对象图成员保存的所有描述性数据

SoapFormatter也类似。

 

 

使用ISerizlizable自定义序列化

   被标记了[Serializable]的对象拥有了实现ISerializable接口的选项。

这个接口就一个方法:

  

  AddValue这个重载很多。

 

 实现了ISerizlizable接口的类型也必须定义一个带有下面签名的特殊构造函数:

 

  

 

 

 例如:

 

    [Serializable]
    public class StringData : ISerializable
    {
        private string dataItemOne = "First data block";
        private string dataItemTwo = "More data";
        public StringData()
        {

        }
        protected StringData(SerializationInfo si,StreamingContext ctx) 
        {
            //从流中得到合并的成员变量
            dataItemOne = si.GetString("First_Item").ToLower();
            dataItemTwo = si.GetString("dataItemTwo").ToLower();
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            //用格式化数据填充SerizlizationInfo对象
            info.AddValue("First_Item", dataItemOne.ToUpper());
            info.AddValue("dataItemTwo", dataItemTwo.ToUpper());
        }
    }
  StringData myData = new StringData();
            SoapFormatter soapFprmat = new SoapFormatter();
            using (Stream fStream=new FileStream("MyData.soap",FileMode.Create,FileAccess.Write,FileShare.None))
            {
                soapFprmat.Serialize(fStream,myData);                
            }

可以简单的完成

        [OnSerializing]
        private void OnSerializing(StreamingContext context)    //需要带上此参数
        {
            //在序列化的过程就调用
            dataItemOne = dataItemOne.ToUpper();
            dataItemTwo = dataItemTwo.ToUpper();
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context) 
        {
            //在反序列化的过程就调用
            dataItemOne = dataItemOne.ToLower();
            dataItemTwo = dataItemTwo.ToLower();
        }

 

这个命名空间介绍完了,涉及的类有点多。。。

 

posted @ 2017-08-29 21:25  Sealee  阅读(259)  评论(0编辑  收藏  举报