• 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();
            }

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

  • 相关阅读:
    扫描与爆破
    复习与PKI技术

    IIS与FTP
    IIS与WEB
    DNS部署与安全
    DHCP服务部署与安全
    文件共享服务CIFS
    NTFS权限
    关于操作运算符的一些小练习
  • 原文地址:https://www.cnblogs.com/Sea1ee/p/7414199.html
Copyright © 2020-2023  润新知