怎么修改网站首页logo,做设计的素材网站有哪些,php做网站后台,制作wordpress模板在计算机世界#xff0c;万物皆01二进制#xff0c;包括各种各样的文件格式和网络协议#xff0c;二进制格式最为常见#xff01;NewLife.Core 内置了完整的二进制序列化框架 Binary#xff0c;经过十多年洗礼#xff0c;发展到了第三代支持Handler处理器扩展。Binary的同… 在计算机世界万物皆01二进制包括各种各样的文件格式和网络协议二进制格式最为常见NewLife.Core 内置了完整的二进制序列化框架 Binary经过十多年洗礼发展到了第三代支持Handler处理器扩展。Binary的同类框架有 Protobuf、Thrift、MessagePack。Nuget包NewLife.Core源码地址https://github.com/NewLifeX/X/tree/master/NewLife.Core/Serialization/Binary主要特性Binary主要功能特性体积极小。Binary是Schemaless架构不包含字段名和序号用最少的字节去保存数据压缩整数。大多数时候Int32字段保存的数字很小采用七位压缩编码整数保存可以减少体积格式简单。尽管Binary只有.NET版但其格式非常简单可以很容易在其它语言上实现支持性很广。Binary设计初衷就是用于实现各种已知文件格式和通信协议例如ZipFile支持动态特性。可根据某些字段值生成不同消息类型例如MQTT和DNS协议可读性较差。二进制格式且没有Schema可读性较差无版本支持。需要读写双方约定好多版本格式的兼容Binary设计理念就是用最小的体积去保存数据且能够灵活实现各种文件格式和通信协议的序列化。直接序列化对象在没有使用额外压缩算法的条件下Binary几乎是结果体积最小的序列化框架。快速用法想要序列化一个对象或者反序列化一个数据流到对象最直接的想法就是这样// 快速读取
public static T FastReadT(Stream stream, Boolean encodeInt true);
// 快速写入
public static Packet FastWrite(Object value, Boolean encodeInt true);
public static void FastWrite(Object value, Stream stream, Boolean encodeInt true);Binary.FastWrite 可以直接把一个对象序列化为数据包Packet可以理解为字节数组Byte[]的包装。Binary.FastRead 从数据流中反序列化得到目标类型的对象这里必须指定目标类型否则Binary不知道应该如何解析。例子[Fact]
public void Fast()
{var model new MyModel { Code 1234, Name Stone };var pk Binary.FastWrite(model);Assert.Equal(8, pk.Total);Assert.Equal(D2090553746F6E65, pk.ToHex());Assert.Equal(0gkFU3RvbmU, pk.ToArray().ToBase64());var model2 Binary.FastReadMyModel(pk.GetStream());Assert.Equal(model.Code, model2.Code);Assert.Equal(model.Name, model2.Name);var ms new MemoryStream();Binary.FastWrite(model, ms);Assert.Equal(D2090553746F6E65, ms.ToArray().ToHex());
}
private class MyModel
{public Int32 Code { get; set; }public String Name { get; set; }
}序列化带有一个整型和一个字符串的对象结果只有8个字节Packet用法可参考此处为语雀文档点击链接查看https://www.yuque.com/go/doc/31527106标准读写Binary主要成员/// summary使用7位编码整数。默认false不使用/summary
public Boolean EncodeInt { get; set; }
/// summary小端字节序。默认false大端/summary
public Boolean IsLittleEndian { get; set; }
/// summary使用指定大小的FieldSizeAttribute特性默认false/summary
public Boolean UseFieldSize { get; set; }
/// summary使用对象引用默认true/summary
public Boolean UseRef { get; set; } true;
/// summary大小宽度。可选0/1/2/4默认0表示压缩编码整数/summary
public Int32 SizeWidth { get; set; }
/// summary要忽略的成员/summary
public ICollectionString IgnoreMembers { get; set; }
/// summary处理器列表/summary
public IListIBinaryHandler Handlers { get; private set; }
/// summary数据流。默认实例化一个内存数据流/summary
public virtual Stream Stream { get; set; }
/// summary主对象/summary
public StackObject Hosts { get; private set; }
/// summary成员/summary
public MemberInfo Member { get; set; }
/// summary字符串编码默认utf-8/summary
public Encoding Encoding { get; set; }
/// summary序列化属性而不是字段。默认true/summary
public Boolean UseProperty { get; set; }
// 处理器
public Binary AddHandler(IBinaryHandler handler);
public Binary AddHandlerTHandler(Int32 priority 0);
public T GetHandlerT();
// 写入
public virtual Boolean Write(Object value, Type type null);
// 读取
public virtual Object Read(Type type);
public T ReadT();
public virtual Boolean TryRead(Type type, ref Object value);Stream 最为重要代表序列化和反序列化的数据流默认实例化一个内存流。EncodeInt 指定使用压缩编码整数效果非常明显IsLittleEndian 部分协议使用大端字节序。UseFieldSize 部分协议的长度位和数据区并没有挨在一起需要借助FieldSizeAttribute特性。例如ZipEntry中有这么一段/// summary文件名长度/summary
private readonly UInt16 FileNameLength;
/// summary扩展数据长度/summary
private readonly UInt16 ExtraFieldLength;
// ZipDirEntry成员
/// summary注释长度/summary
private readonly UInt16 CommentLength;
// ZipDirEntry成员
/// summary分卷号。/summary
public UInt16 DiskNumber;
// ZipDirEntry成员
/// summary内部文件属性/summary
public UInt16 InternalFileAttrs;
// ZipDirEntry成员
/// summary扩展文件属性/summary
public UInt32 ExternalFileAttrs;
// ZipDirEntry成员
/// summary文件头相对位移/summary
public UInt32 RelativeOffsetOfLocalHeader;
/// summary文件名如果是目录则以/结束/summary
[FieldSize(FileNameLength)]
public String FileName;
/// summary扩展字段/summary
[FieldSize(ExtraFieldLength)]
public Byte[] ExtraField;
// ZipDirEntry成员
/// summary注释/summary
[FieldSize(CommentLength)]
public String Comment;IgnoreMembers 指定某些成员不参与序列化支持动态指定。例如ZipFile的目录实体和文件实体需要序列化的字段有所不同。Encoding 指定序列化字符串时使用的文本编码。设置好各种参数后就可以Write/Read来序列化或反序列化对象了。安全起见建议每个Binary只用一次重复使用可能有意想不到的后果。自定义扩展Binary设计时使用Handler处理器架构Write/Read内部实际上是逐个遍历Handler直到找到能够处理的Handler为止。因此Handler也有优先级其中基础数据类型BinaryGeneral处理器优先级最高。BinaryGeneral 负责处理数字、布尔、时间日期、字符串等等基础数据类型。BinaryNormal 负责处理字节数组、Guid、Packet等常见类型。BinaryList 负责处理数组和列表。BinaryDictionary 负责处理字典。BinaryComposite 负责处理复杂对象反射各成员递归序列化。该处理器优先级最低。来看看怎么样自定义一个处理器以颜色处理器为例/// summary颜色处理器。/summary
public class BinaryColor : BinaryHandlerBase
{/// summary实例化/summarypublic BinaryColor(){Priority 0x50;}/// summary写入对象/summary/// param namevalue目标对象/param/// param nametype类型/param/// returns/returnspublic override Boolean Write(Object value, Type type){if (type ! typeof(Color)) return false;var color (Color)value;WriteLog(WriteColor {0}, color);Host.Write(color.A);Host.Write(color.R);Host.Write(color.G);Host.Write(color.B);return true;}/// summary尝试读取指定类型对象/summary/// param nametype/param/// param namevalue/param/// returns/returnspublic override Boolean TryRead(Type type, ref Object value){if (type ! typeof(Color)) return false;var a Host.ReadByte();var r Host.ReadByte();var g Host.ReadByte();var b Host.ReadByte();var color Color.FromArgb(a, r, g, b);WriteLog(ReadColor {0}, color);value color;return true;}
}最后只需要挂载到Binary上即可序列化和反序列化带有Color类型的成员var bn new Binary();
bn.AddHandlerBinaryColor();总结.NET内部自带二进制序列化BinaryFormatter它会带上大量额外信息导致体积很大基本上很少用到。Binary设计的初衷是序列化各种文件格式和通信协议因此并没有过多考虑作为RPC通信格式。实际上NewLife组件自己的RPC框架ApiServer并没有使用Binary而是选择了兼容性比较好的Json。在中通的100亿Redis大数据中尽管是二进制kv数据同样没有用到Binary。因为它需要对字节数据进行极致控制并且需要做多版本兼容。因此它实际上是直接读写二进制数据流然后借用了Binary的一些辅助方法。