<?xml:namespace prefix = o />

在开发某些需要跟第三方平台交互的项目时,往往需要解析或者构造符合对方协议要求的数据格式,该操作在.Net中有个很漂亮的名字——序列化!

在实际使用中,XML序列化用得比较多,二进制序列化也不错,只是可控性很低。当然,对于要序列化指定协议的格式而言,它们就几乎帮不上忙了。于是有了“协议序列化组件NewLife.Serialization”。

协议序列化类ProtocolFormatter的主旨是实现二进制格式数据和.Net实体数据之间的灵活转换!

使用上非常简单,下面通过实现一个简单的消息类来反序列化手机QQ2008(Mobile)的聊天记录。

新建一个控制台项目,引用NewLife.Serialization.dll。加入下面的代码:

FileStream stream = new FileStream("10000.rec", FileMode.Open);
ProtocolFormatter formatter = new ProtocolFormatter(typeof(Message));
formatter.Head.Config.NoHead = true;
while (stream.Position < stream.Length)
{try{Message msg = new Message();formatter.Deserialize(stream, msg);Console.WriteLine("{0}({1}) {2} {3}", msg.Name, msg.Number, msg.Time, msg.MsgKind);Console.WriteLine(msg.Content);if (BitConverter.ToString(msg.Data) != "00-00-00-00-00")Console.WriteLine("未知数据:{0}", BitConverter.ToString(msg.Data));Console.WriteLine();}catch (EndOfStreamException) { break; }
}
stream.Close();

第一步实例化一个ProtocolFormatter对象,这里指定了类型为Message;

第二步实例化一个Message对象,这点跟许多组件的反序列化不同,因为有时候外部已经准备好了一个对象,反序列化只需要填充就可以了;

第三步就是序列化,这里传入第二步实例化的对象。如果这里传入对象,第一步实例化ProtocolFormatter的时候,就可以不用指定类型了;这里也可以不传入对象,Deserialize方法内部会实例化一个返回。

下面我们看看Message类:

[ProtocolSerialProperty]
public class Message : IProtocolSerializable
{#region 属性private Int16 _Length;/// <summary>消息长度</summary>public Int16 Length{get { return _Length; }set { _Length = value; }}private String _Content;/// <summary>内容</summary>public String Content{get { return _Content; }set { _Content = value; }}private Int32 _Number;/// <summary>号码</summary>public Int32 Number{get { return _Number; }set { _Number = value; }}private String _Name;/// <summary>名称</summary>public String Name{get { return _Name; }set { _Name = value; }}private DateTime _Time;/// <summary>时间</summary>public DateTime Time{get { return _Time; }set { _Time = value; }}private Int16 _Unknown;/// <summary>未知</summary>public Int16 Unknown{get { return _Unknown; }set { _Unknown = value; }}private MsgKinds _MsgKind;/// <summary>消息类型</summary>public MsgKinds MsgKind{get { return _MsgKind; }set { _MsgKind = value; }}private Byte[] _Data;/// <summary>未知数据</summary>public Byte[] Data{get { return _Data; }set { _Data = value; }}#endregion#region 方法const Char tag = (Char)20;static String FixContent(String content){content = content.Replace(tag + "A", "[/惊讶]");content = content.Replace(tag + "N", "[/呲牙]");content = content.Replace(tag + "M", "[/调皮]");content = content.Replace(tag + "x", "[/惊恐]");content = content.Replace(tag + "J", "[/大哭]");content = content.Replace(tag + "s", "[/难过]");content = content.Replace(tag + "e", "[/爱心]");content = content.Replace(tag + "o", "[/强]");content = content.Replace(tag + "K", "[/尴尬]");content = content.Replace(tag + "C", "[/色]");content = content.Replace(tag + "\\", "[/饱]");content = content.Replace(tag + "E", "[/得意]");content = content.Replace(tag + "b", "[/玫瑰]");content = content.Replace(tag + "v", "[/抓狂]");content = content.Replace(tag.ToString() + (Char)139, "[/可爱]");content = content.Replace(tag.ToString() + (Char)153, "[/再见]");content = content.Replace(tag.ToString() + (Char)138, "[/偷笑]");content = content.Replace(tag.ToString() + (Char)121, "[/流汗]");content = content.Replace(tag.ToString() + (Char)162, "[/擦汗]");content = content.Replace(tag.ToString() + (Char)171, "[/委屈]");content = content.Replace(tag.ToString() + (Char)141, "[/傲慢]");content = content.Replace(tag.ToString() + (Char)197, "[/献吻]");content = content.Replace(tag.ToString() + (Char)146, "[/疑问]");content = content.Replace(tag.ToString() + (Char)166, "[/坏笑]");content = content.Replace(tag.ToString() + (Char)149, "[/折磨]");content = content.Replace(tag.ToString() + (Char)168, "[/右哼哼]");content = content.Replace(tag.ToString() + (Char)170, "[/鄙视]");content = content.Replace(tag.ToString() + (Char)172, "[/快哭了]");content = content.Replace(tag.ToString() + (Char)181, "[/示爱]");content = content.Replace(tag.ToString() + (Char)140, "[/白眼]");content = content.Replace(tag.ToString() + (Char)174, "[/爱情]");content = content.Replace(tag.ToString() + (Char)182, "[/瓢虫]");content = content.Replace(tag.ToString() + (Char)161, "[/冷汗]");//if (content.Contains(tag.ToString())) throw new Exception("未识别!");return content;}#endregion#region IProtocolSerializable 成员object IProtocolSerializable.OnCreateInstance(ReadContext context, Type type){return null;}void IProtocolSerializable.OnDeserialized(ReadContext context){}bool IProtocolSerializable.OnDeserializing(ReadContext context){BinaryReader reader = context.Reader;if (context.Node.Name == "Content"){context.Data = ReadString(context.Reader);return false;}else if (context.Node.Name == "Name"){context.Data = ReadString2(context.Reader);return false;}else if (context.Node.Name == "Time"){Int32[] ds = new Int32[7];Int32 m = 0;for (int i = 0; i < ds.Length; i++){ds[i] = reader.ReadInt16();}DateTime dt = new DateTime(ds[0], ds[1], ds[3], ds[4], ds[5], ds[2], DateTimeKind.Utc);context.Data = dt.ToLocalTime();return false;}else if (context.Node.Name == "Data"){context.Data = context.Reader.ReadBytes(5);return false;}return true;}static String ReadString(BinaryReader reader){Int32 msglen = reader.ReadInt16();if (reader.BaseStream.Position > 4) msglen = reader.ReadInt16();Byte[] buffer = reader.ReadBytes(msglen);String str = Encoding.Unicode.GetString(buffer);str = FixContent(str);return str;}static String ReadString2(BinaryReader reader){Int32 msglen = reader.ReadInt16();Byte[] buffer = reader.ReadBytes(msglen * 2);String str = Encoding.Unicode.GetString(buffer);str = FixContent(str);return str;}void IProtocolSerializable.OnSerialized(WriteContext context){}bool IProtocolSerializable.OnSerializing(WriteContext context){return true;}#endregion
}public enum MsgKinds : short{系统消息 = 0x110,带链接系统消息 = 0x116,新邮件 = 0x117,请求加好友 = 0x122,通过加好友请求 = 0x0123}

Message类主要包含三大部分:

第一是属性,这点从分析手机QQ2008聊天记录文件的格式可以得出。我是一边试一遍猜,猜出来的;

第二是重点。这个类实现了IProtocolSerializable接口,通过OnDeserializing来改变反序列化的行为,某些属性需要特殊处理的,就在这里处理。

第三部分是处理聊天记录里面的表情,这个可有可无。

Message类上面有个ProtocolSerialProperty特性,指定反序列化的时候,分析属性,而不是默认的分析字段。这里指定分析属性,只是为了方便下面写代码判别名称。

执行效果如下:

协议序列化组件完全通过反射实现,层层深入,所以性能非常差!我们主要用来序列化BT种子以及各种用于网络传输的指令,因为指令对象简单,性能上还可以接受。

大石头

新生命开发团队

2010-09-29 10758

组件示例下载

8,协议序列化组件NewLife.Serialization相关推荐

  1. Rest Framework:序列化组件

    Django内置的serializers(把对象序列化成json字符串 from django.core import serializersdef test(request):book_list = ...

  2. drf3 Serializers 序列化组件

    为什么要用序列化组件 做前后端分离的项目,我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 给前端数据的时候都要转成json格式,那就需要对从数据库拿到的数据进行序列化. ...

  3. DAY97 - Rest Framework(二)- 序列化组件之Serializer和ModelSerializer

    一.序列化组件之Serializer from django.http import JsonResponse from rest_framework.views import APIView fro ...

  4. DRF的序列化——Serializers 序列化组件

    为什么要用序列化组件 当我们做前后端分离的项目~~ 我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 那么我们给前端数据的时候都要转成json格式,那就需要对我们从数据库 ...

  5. Rest Framework:二、序列化组件

    一.序列化组件 环境配置: 使django支持Mysql(前面已有介绍,这里不再重复) 使django支持 framework 在settings.py中的INSTALLED_APPS字段添加: &q ...

  6. Django框架(十九)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import modelsclass Book(models.Model): nid = models.AutoField(primary_key ...

  7. Django rest framework 序列化组件

    在笔者认为,在Django rest framework中最重要的是序列化组件,通过序列化我们可以将我们后台数据通过一定格式发送到我们的前端,然后通过一定的方法展示我们的数据. 那么我们就开始介绍我们 ...

  8. Django DRF认证组件/权限组件/序列化组件综合总结(完整版)

    本代码完成的功能是: 1.根据token判断用户登录状态,然后提示用户是否登陆, 2.用户登录后,根据用户类型判断用户是否有权限查看资料 使用rest_framework一定要在配置文件设置先设置 ' ...

  9. APIView与序列化组件使用

    APIView基本使用 1.什么是APIView Django中视图views.py有两种一种是基于类的实现另一种是函数的实现,而APIView就是REST framework提供的所有视图的基类,继 ...

最新文章

  1. 清华团队让 AI 写诗“更上一层楼”,诗歌图灵测试迷惑近半数玩家
  2. 以下用于数据存储领域的python第三方库是-南开《网络爬虫与信息提取》19秋期末考核题目【标准答案】...
  3. 网易2022秋季校园招聘-通用技术A卷-0821
  4. 我的第一个项目催生的前世今生(LAIS,LKJ,DTU,记录器)
  5. TOMCAT启动提示NB: JAVA_HOME should point to a JDK not a JRE解决
  6. 人脸检测——FDDB数据集评估
  7. verilog 中的 log2
  8. 源码解析 深入vue响应式原理
  9. 一分钟五类果汁喝掉熊猫眼
  10. Velodyne获取PCAP文件时间戳
  11. STM32F103 读写内部FLASH—学习笔记(野火)
  12. 最佳37个获取LOGO设计灵感的网站推荐
  13. E575: viminfo: Illegal starting char in line: hello=Hello\ \!\How\ are\ you\ \?
  14. 山东省下载准考证必须用电脑吗
  15. 与上司同事的谈话技巧
  16. Java—方法的使用
  17. [面经]阿里游戏一面的算法题
  18. post发送请求工具类
  19. matlab绘制渐变色单柱状图
  20. kind kubernetes 集群内如何通过 helm 部署定制化 Prometheus-Operator?

热门文章

  1. python mysqldb cursor_python中MySQLdb模块用法实例
  2. poj1182 and 携程预赛2第一题 带权并查集
  3. 【错误记录】编译 Linux 内核报错 ( fatal error: openssl/opensslv.h: No such file or directory )
  4. 【Android 逆向】Android 逆向通用工具开发 ( PC 端工程分析 | 网络初始化操作 | PC 端工程核心业务逻辑 )
  5. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 )
  6. 【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 )
  7. [POJ 3345] Bribing FIPA
  8. 病毒木马防御与分析实战
  9. zabbix系列之九——添加钉钉告警
  10. PostgreSQL查询优化器之grouping_planner