首页 > 学院 > 开发设计 > 正文

c# vs2012 序列化(Serialize)和反序列化(Deserialize)实际应用

2019-11-06 06:42:09
字体:
来源:转载
供稿:网友

c# vs2012 序列化(Serialize)和反序列化(Deserialize)实际应用

c#中序列化和反序列化又称之为串行化,能够使运行的中的数据结构及数据能够长时间保存起来,用以后面的使用。本文也就实际项目来说明。

一.TCP通信

从初步建立TCP连接,到发送验证数据包数据,这边就需要向服务器发送数据。发送的数据是验证信息,就简单来说,如果是一个字符串,这里面我们用TCP可以直接写入流就行了:

//客户端 string content = "发送的数据"; Byte[] bytSend = Encoding.UTF8.GetBytes(content); ntwStream.Write(bytSend, 0, bytSend.Length);

而相对应的服务器接收数据应该是这样:

//服务器listener.Listen(0); Socket socket = listener.Accept(); NetworkStream ntwStream = new NetworkStream(socket); StreamReader strmReader = new StreamReader(ntwStream); strmReader.ReadToEnd()

这种传输数据结构相对很简单的TCP可以直接传输即可,但是对于相对复杂的结构的数据,类的实例,需要的数据有int,string,还有文件列表List<>等等,那么简单数据传输就不适用了(也可以简单传输,但是解析相对困难),这时候就需要序列化(后面有复杂结构示例),下面就以验证数据包来说明,数据包包括登录名和密码

//在要序列化的类上面加上[Serializable]声明这个类是可以序列化的[Serializable]public class LoginInfo{//登入数据包. public String strUID = null;//用户名 public String strPWD = null;//密码. public Int32 iState = 0;//状态值. }

客户端发送验证数据包

//客户端System.Runtime.Serialization.Formatters.Binary.BinaryFormatter mBinaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();try{ //连接服务器 ClientTcp.Connect(System.Net.ipAddress.Parse(strIPAddr),iPort); //发送验证数据包 LoginInfo mLoginInfo = new LoginInfo(); mLoginInfo.strPWD = "passWord"; mLoginInfo.strUID = "administrator"; mLoginInfo.iState = bIsShowListMsg ? 100 : 0; mBinaryFormatter.Serialize(ClientTcp.GetStream(), mLoginInfo); object oNetData = mBinaryFormatter.Deserialize(ClientTcp.GetStream()); ReturnInfoValue mReturnValue = oNetData as ReturnInfoValue; if (mReturnValue == null) return null; if (mReturnValue.iReturnValue == VideoStreamCommon.NetPacket.RIV_ERROE) return null; return ClientTcp; } catch (System.Exception error) { MessageBox.Show("创建TCP发生异常,异常信息:" + error.Message); }

服务器接收验证包

try{ listenerTcp.Start(); do { TcpClient mClientTcp = listenerTcp.AcceptTcpClient(); if (mClientTcp == null) break; oNetData = mBinaryFormatter.Deserialize(mThreadParam.ClientTcp.GetStream()); if (bIsCheckClient == false) {//先验证数据. int iTepValue = CheckClientInfo(oNetData); if (iTepValue == 2) {//创建消息窗口. AsyncSetWorkThreadParam(ref mThreadParam, 1001, true);//添加线消息窗口列表. } bIsCheckClient = (iTepValue != 0); if (bIsCheckClient) continue;//验证数据成功. else break; //验证数据失败. } } while (true);}catch (System.Exception ep){//系统异常. ep.Message.ToString(); AsyncAddListMessage("端口被占用:" + strIPAddr, 0);}

验证数据函数

/// <summary>/// 验证连接是否合法./// </summary>/// <param name="param"></param>/// <returns></returns>public int CheckClientInfo(object param){ LoginInfo mLoginInfo = param as LoginInfo; if (mLoginInfo == null) return 0; if(mLoginInfo.strUID == "administrator" && mLoginInfo.strPWD == "password") { return 1; } else { return 0; }}

二.进程间数据传递

当程序功能化之后,每个人负责不同模块,这就会涉及到创建一个进程,然后向该进程传递必要的参数,如果参数中数据结构比较复杂也得使用序列化,调用进程序列化文件后,被调用进程再解析该文件,实现数据传递。下面上代码:

[Serializable] public class Param { public List<Param.CHANNEL_INFO> channelList;//通道列表 public string fileid; public int isFullDiskPlay; public string strIP; public string strPort; public Param(); [Serializable] public class CHANNEL_INFO { public List<Param.FILE_INFO> fileList; public int id; public string name; public CHANNEL_INFO(); } [Serializable] public class FILE_INFO { public DateTime dtBegin; public DateTime dtEnd; public string name; public FILE_INFO(); } public bool SeveToFile(string strFileName) { try { IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream(strFileName, FileMode.Create, Fileaccess.Write, FileShare.None); formatter.Serialize(stream, this); stream.Close(); return true; } catch (System.Exception ex) { return false; } } public static Param LoadFromFile(string strFileName) { try { IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read); VideoStreamParam_Hik video = formatter.Deserialize(stream) as VideoStreamParam_Hik; stream.Close(); return video; } catch (System.Exception ex) { return null; } } }

下面是调用部分

//序列化文件名称(GUID名称)strFileName = Guid.NewGuid().ToString() + ".bin";//保存到bin文件if (!videomodel.SeveToFile(strFileName)){ MessageBox.Show("测试失败"); return;}//开启一个进程System.Diagnostics.PRocess PlayStream = new System.Diagnostics.Process();PlayStream.StartInfo.UseShellExecute = false;PlayStream.StartInfo.Arguments = strFileName;PlayStream.StartInfo.CreateNoWindow = true;PlayStream.StartInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + "test.exe";PlayStream.Start();

最后是调用解析部分,该部分再test.exe中

/// <summary>/// 从文件中反序列化出所需要的数据/// </summary>/// <param name="strFileName">文件名(完全路径)</param>/// <param name="qcjl_displayTable">全程记录表</param>/// <returns></returns>public bool LoadFromFile(string strFileName, ref Param param){ try { IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read); param = new Param(); param = (Param)formatter.Deserialize(stream); stream.Close(); return true; } catch (System.Exception ex) { MessageBox.Show("反序列化发生异常!,异常信息:" + ex.Message); return false; }}

上面反序列化的实例和传递的部分是一样的,这样就可以使用其中的参数了。 最后还要说明一下,序列化和反序列化的的类应该使用公用的类,即定义一个两个程序公用的类,都调用该公共的dll,而不能定义两个相同的类结构,不然在反序列化中不能匹配,转化出错。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表