mirror of
https://github.com/RRQM/TouchSocket.git
synced 2025-12-19 01:46:44 +08:00
917 lines
26 KiB
C#
917 lines
26 KiB
C#
//------------------------------------------------------------------------------
|
||
// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
|
||
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||
// Github源代码仓库:https://github.com/RRQM
|
||
// API首页:https://www.yuque.com/eo2w71/rrqm
|
||
// 交流QQ群:234762506
|
||
// 感谢您的下载和使用
|
||
//------------------------------------------------------------------------------
|
||
//------------------------------------------------------------------------------
|
||
|
||
using RRQMCore.Serialization;
|
||
using RRQMCore.XREF.Newtonsoft.Json;
|
||
using System;
|
||
using System.IO;
|
||
using System.Text;
|
||
|
||
namespace RRQMCore.ByteManager
|
||
{
|
||
/// <summary>
|
||
/// 字节块流
|
||
/// </summary>
|
||
public sealed class ByteBlock : Stream, IDisposable
|
||
{
|
||
internal bool @using;
|
||
|
||
internal long length;
|
||
|
||
private static float ratio = 1.5f;
|
||
|
||
private byte[] _buffer;
|
||
|
||
private bool holding;
|
||
|
||
private long position;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="byteSize"></param>
|
||
/// <param name="equalSize"></param>
|
||
public ByteBlock(int byteSize = 1024 * 10, bool equalSize = false) : this(BytePool.GetByteCore(byteSize, equalSize))
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
|
||
/// </summary>
|
||
public int CanReadLen
|
||
{
|
||
get { return this.Len - this.Pos; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 还能读取的长度,计算为<see cref="Len"/>与<see cref="Pos"/>的差值。
|
||
/// </summary>
|
||
public long CanReadLength
|
||
{
|
||
get { return this.length - this.position; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="bytes"></param>
|
||
internal ByteBlock(byte[] bytes)
|
||
{
|
||
this.@using = true;
|
||
this._buffer = bytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扩容增长比,默认为1.5,
|
||
/// min:1.5
|
||
/// </summary>
|
||
public static float Ratio
|
||
{
|
||
get { return ratio; }
|
||
set
|
||
{
|
||
if (value < 1.5)
|
||
{
|
||
value = 1.5f;
|
||
}
|
||
ratio = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 字节实例
|
||
/// </summary>
|
||
public byte[] Buffer
|
||
{
|
||
get { return this._buffer; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 可读取
|
||
/// </summary>
|
||
public override bool CanRead => this.@using;
|
||
|
||
/// <summary>
|
||
/// 支持查找
|
||
/// </summary>
|
||
public override bool CanSeek => this.@using;
|
||
|
||
/// <summary>
|
||
/// 可写入
|
||
/// </summary>
|
||
public override bool CanWrite => this.@using;
|
||
|
||
/// <summary>
|
||
/// 容量
|
||
/// </summary>
|
||
public int Capacity => this._buffer.Length;
|
||
|
||
/// <summary>
|
||
/// 表示持续性持有,为True时,Dispose将调用无效。
|
||
/// </summary>
|
||
public bool Holding
|
||
{
|
||
get { return this.holding; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Int真实长度
|
||
/// </summary>
|
||
public int Len
|
||
{ get { return (int)this.length; } }
|
||
|
||
/// <summary>
|
||
/// 真实长度
|
||
/// </summary>
|
||
public override long Length
|
||
{ get { return this.length; } }
|
||
|
||
/// <summary>
|
||
/// int型流位置
|
||
/// </summary>
|
||
public int Pos
|
||
{
|
||
get { return (int)this.position; }
|
||
set { this.position = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 流位置
|
||
/// </summary>
|
||
public override long Position
|
||
{
|
||
get { return this.position; }
|
||
set { this.position = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 使用状态
|
||
/// </summary>
|
||
public bool Using
|
||
{
|
||
get { return this.@using; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接完全释放,游离该对象,然后等待GC
|
||
/// </summary>
|
||
public void AbsoluteDispose()
|
||
{
|
||
this.holding = false;
|
||
this.@using = false;
|
||
this.position = 0;
|
||
this.length = 0;
|
||
this._buffer = default;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空数据
|
||
/// </summary>
|
||
/// <exception cref="ByteBlockDisposedException">内存块已释放</exception>
|
||
public void Clear()
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
Array.Clear(this._buffer, 0, this._buffer.Length);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收资源
|
||
/// </summary>
|
||
public new void Dispose()
|
||
{
|
||
if (this.holding)
|
||
{
|
||
return;
|
||
}
|
||
if (this.@using)
|
||
{
|
||
lock (this)
|
||
{
|
||
if (this.@using)
|
||
{
|
||
GC.SuppressFinalize(this);
|
||
BytePool.Recycle(this._buffer);
|
||
this.AbsoluteDispose();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无实际效果
|
||
/// </summary>
|
||
public override void Flush()
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取
|
||
/// </summary>
|
||
/// <param name="buffer"></param>
|
||
/// <param name="offset"></param>
|
||
/// <param name="count"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public override int Read(byte[] buffer, int offset, int count)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
int len = this._buffer.Length - this.position > count ? count : this._buffer.Length - (int)this.position;
|
||
Array.Copy(this._buffer, this.position, buffer, offset, len);
|
||
this.position += len;
|
||
return len;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取数据
|
||
/// </summary>
|
||
/// <param name="buffer"></param>
|
||
/// <returns></returns>
|
||
public int Read(byte[] buffer)
|
||
{
|
||
return this.Read(buffer, 0, buffer.Length);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置流位置
|
||
/// </summary>
|
||
/// <param name="offset"></param>
|
||
/// <param name="origin"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public override long Seek(long offset, SeekOrigin origin)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
switch (origin)
|
||
{
|
||
case SeekOrigin.Begin:
|
||
this.position = offset;
|
||
break;
|
||
|
||
case SeekOrigin.Current:
|
||
this.position += offset;
|
||
break;
|
||
|
||
case SeekOrigin.End:
|
||
this.position = this.length + offset;
|
||
break;
|
||
}
|
||
return this.position;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新设置容量
|
||
/// </summary>
|
||
/// <param name="size">新尺寸</param>
|
||
/// <param name="retainedData">是否保留元数据</param>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public void SetCapacity(int size, bool retainedData = false)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
byte[] bytes = new byte[size];
|
||
|
||
if (retainedData)
|
||
{
|
||
Array.Copy(this._buffer, 0, bytes, 0, this._buffer.Length);
|
||
}
|
||
BytePool.Recycle(this._buffer);
|
||
this._buffer = bytes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置持续持有属性,当为True时,调用Dispose会失效,表示该对象将长期持有,直至设置为False。
|
||
/// 当为False时,会自动调用Dispose。
|
||
/// </summary>
|
||
/// <param name="holding"></param>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public void SetHolding(bool holding)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
this.holding = holding;
|
||
if (!holding)
|
||
{
|
||
this.Dispose();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置实际长度
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public override void SetLength(long value)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
if (value > this._buffer.Length)
|
||
{
|
||
throw new RRQMException("设置值超出容量");
|
||
}
|
||
this.length = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为有效内存
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public byte[] ToArray()
|
||
{
|
||
return this.ToArray(0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从指定位置转化到有效内存
|
||
/// </summary>
|
||
/// <param name="offset"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public byte[] ToArray(int offset)
|
||
{
|
||
return this.ToArray(offset, (int)(this.length - offset));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从指定位置转化到指定长度的有效内存
|
||
/// </summary>
|
||
/// <param name="offset"></param>
|
||
/// <param name="length"></param>
|
||
/// <returns></returns>
|
||
public byte[] ToArray(int offset, int length)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
byte[] buffer = new byte[length];
|
||
Array.Copy(this._buffer, offset, buffer, 0, buffer.Length);
|
||
return buffer;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入
|
||
/// </summary>
|
||
/// <param name="buffer"></param>
|
||
/// <param name="offset"></param>
|
||
/// <param name="count"></param>
|
||
/// <exception cref="ByteBlockDisposedException"></exception>
|
||
public override void Write(byte[] buffer, int offset, int count)
|
||
{
|
||
if (!this.@using)
|
||
{
|
||
throw new ByteBlockDisposedException(ResType.ByteBlockDisposed.GetResString());
|
||
}
|
||
if (this._buffer.Length - this.position < count)
|
||
{
|
||
int need = this._buffer.Length + count - ((int)(this._buffer.Length - this.position));
|
||
int lend = this._buffer.Length;
|
||
while (need > lend)
|
||
{
|
||
lend = (int)(lend * ratio);
|
||
}
|
||
this.SetCapacity(lend, true);
|
||
}
|
||
Array.Copy(buffer, offset, this._buffer, this.position, count);
|
||
this.position += count;
|
||
this.length += count;
|
||
if (this.length < this.position)
|
||
{
|
||
this.length = this.position;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入
|
||
/// </summary>
|
||
/// <param name="buffer"></param>
|
||
/// <returns></returns>
|
||
public void Write(byte[] buffer)
|
||
{
|
||
this.Write(buffer, 0, buffer.Length);
|
||
}
|
||
|
||
#region BytesPackage
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个独立的<see cref="byte"/>数组包
|
||
/// </summary>
|
||
public byte[] ReadBytesPackage()
|
||
{
|
||
byte status = this.ReadByte();
|
||
if (status == 0)
|
||
{
|
||
return null;
|
||
}
|
||
int length = this.ReadInt32();
|
||
byte[] data = new byte[length];
|
||
Array.Copy(this._buffer, this.position, data, 0, length);
|
||
this.position += length;
|
||
return data;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 尝试获取数据包信息,方便从Buffer操作数据
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <param name="len"></param>
|
||
/// <returns></returns>
|
||
public bool TryReadBytesPackageInfo(out int pos, out int len)
|
||
{
|
||
byte status = this.ReadByte();
|
||
if (status == 0)
|
||
{
|
||
pos = 0;
|
||
len = 0;
|
||
return false;
|
||
}
|
||
len = this.ReadInt32();
|
||
pos = (int)this.position;
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入一个独立的<see cref="byte"/>数组包
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <param name="offset"></param>
|
||
/// <param name="length"></param>
|
||
public ByteBlock WriteBytesPackage(byte[] value, int offset, int length)
|
||
{
|
||
if (value == null)
|
||
{
|
||
this.Write((byte)0);
|
||
}
|
||
else
|
||
{
|
||
this.Write((byte)1);
|
||
this.Write(length);
|
||
this.Write(value, offset, length);
|
||
}
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入一个独立的<see cref="byte"/>数组包
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock WriteBytesPackage(byte[] value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
return this.WriteBytesPackage(value, 0, 0);
|
||
}
|
||
return this.WriteBytesPackage(value, 0, value.Length);
|
||
}
|
||
|
||
#endregion BytesPackage
|
||
|
||
#region Int32
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="int"/>值
|
||
/// </summary>
|
||
public int ReadInt32()
|
||
{
|
||
int value = RRQMBitConverter.Default.ToInt32(this._buffer, (int)this.position);
|
||
this.position += 4;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="int"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(int value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Int32
|
||
|
||
#region Int16
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="short"/>值
|
||
/// </summary>
|
||
public short ReadInt16()
|
||
{
|
||
short value = RRQMBitConverter.Default.ToInt16(this._buffer, (int)this.position);
|
||
this.position += 2;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="short"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(short value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Int16
|
||
|
||
#region Int64
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="long"/>值
|
||
/// </summary>
|
||
public long ReadInt64()
|
||
{
|
||
long value = RRQMBitConverter.Default.ToInt64(this._buffer, (int)this.position);
|
||
this.position += 8;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="long"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(long value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Int64
|
||
|
||
#region Boolean
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="bool"/>值
|
||
/// </summary>
|
||
public bool ReadBoolean()
|
||
{
|
||
bool value = RRQMBitConverter.Default.ToBoolean(this._buffer, (int)this.position);
|
||
this.position += 1;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="bool"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(bool value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Boolean
|
||
|
||
#region Byte
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="byte"/>值
|
||
/// </summary>
|
||
public new byte ReadByte()
|
||
{
|
||
byte value = this._buffer[this.position];
|
||
this.position++;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="byte"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <returns></returns>
|
||
public ByteBlock Write(byte value)
|
||
{
|
||
this.Write(new byte[] { value }, 0, 1);
|
||
return this;
|
||
}
|
||
|
||
#endregion Byte
|
||
|
||
#region String
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="string"/>值
|
||
/// </summary>
|
||
public string ReadString()
|
||
{
|
||
byte value = this.ReadByte();
|
||
if (value == 0)
|
||
{
|
||
return null;
|
||
}
|
||
else if (value == 1)
|
||
{
|
||
return string.Empty;
|
||
}
|
||
else
|
||
{
|
||
ushort len = this.ReadUInt16();
|
||
string str = Encoding.UTF8.GetString(this._buffer, (int)this.position, len);
|
||
this.position += len;
|
||
return str;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="string"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(string value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
this.Write((byte)0);
|
||
}
|
||
else if (value == string.Empty)
|
||
{
|
||
this.Write((byte)1);
|
||
}
|
||
else
|
||
{
|
||
this.Write((byte)2);
|
||
byte[] buffer = Encoding.UTF8.GetBytes(value);
|
||
if (buffer.Length > ushort.MaxValue)
|
||
{
|
||
throw new RRQMException("传输长度超长");
|
||
}
|
||
this.Write((ushort)buffer.Length);
|
||
this.Write(buffer);
|
||
}
|
||
return this;
|
||
}
|
||
|
||
#endregion String
|
||
|
||
#region Char
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="char"/>值
|
||
/// </summary>
|
||
public char ReadChar()
|
||
{
|
||
char value = RRQMBitConverter.Default.ToChar(this._buffer, (int)this.position);
|
||
this.position += 2;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="char"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(char value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Char
|
||
|
||
#region Double
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="double"/>值
|
||
/// </summary>
|
||
public double ReadDouble()
|
||
{
|
||
double value = RRQMBitConverter.Default.ToDouble(this._buffer, (int)this.position);
|
||
this.position += 8;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="double"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(double value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Double
|
||
|
||
#region Float
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="float"/>值
|
||
/// </summary>
|
||
public float ReadFloat()
|
||
{
|
||
float value = RRQMBitConverter.Default.ToSingle(this._buffer, (int)this.position);
|
||
this.position += 4;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="float"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(float value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion Float
|
||
|
||
#region UInt16
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="ushort"/>值
|
||
/// </summary>
|
||
public ushort ReadUInt16()
|
||
{
|
||
ushort value = RRQMBitConverter.Default.ToUInt16(this._buffer, (int)this.position);
|
||
this.position += 2;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="ushort"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(ushort value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion UInt16
|
||
|
||
#region UInt32
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="uint"/>值
|
||
/// </summary>
|
||
public uint ReadUInt32()
|
||
{
|
||
uint value = RRQMBitConverter.Default.ToUInt32(this._buffer, (int)this.position);
|
||
this.position += 4;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="uint"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(uint value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion UInt32
|
||
|
||
#region UInt64
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="ulong"/>值
|
||
/// </summary>
|
||
public ulong ReadUInt64()
|
||
{
|
||
ulong value = RRQMBitConverter.Default.ToUInt64(this._buffer, (int)this.position);
|
||
this.position += 8;
|
||
return value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="ulong"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(ulong value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value));
|
||
return this;
|
||
}
|
||
|
||
#endregion UInt64
|
||
|
||
#region DateTime
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个<see cref="DateTime"/>值
|
||
/// </summary>
|
||
public DateTime ReadDateTime()
|
||
{
|
||
long value = RRQMBitConverter.Default.ToInt64(this._buffer, (int)this.position);
|
||
this.position += 8;
|
||
return DateTime.FromBinary(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="DateTime"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
public ByteBlock Write(DateTime value)
|
||
{
|
||
this.Write(RRQMBitConverter.Default.GetBytes(value.ToBinary()));
|
||
return this;
|
||
}
|
||
|
||
#endregion DateTime
|
||
|
||
#region Object
|
||
|
||
/// <summary>
|
||
/// 从当前流位置读取一个泛型值
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="serializationType"></param>
|
||
/// <returns></returns>
|
||
public T ReadObject<T>(SerializationType serializationType = SerializationType.RRQMBinary)
|
||
{
|
||
int length = this.ReadInt32();
|
||
|
||
if (length == 0)
|
||
{
|
||
return default;
|
||
}
|
||
|
||
T obj;
|
||
|
||
switch (serializationType)
|
||
{
|
||
case SerializationType.RRQMBinary:
|
||
{
|
||
obj = SerializeConvert.RRQMBinaryDeserialize<T>(this._buffer, (int)this.position);
|
||
}
|
||
break;
|
||
|
||
case SerializationType.Json:
|
||
{
|
||
string jsonString = Encoding.UTF8.GetString(this._buffer, (int)this.position, length);
|
||
obj = JsonConvert.DeserializeObject<T>(jsonString);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
throw new RRQMException("未定义的序列化类型");
|
||
}
|
||
|
||
this.position += length;
|
||
return obj;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写入<see cref="object"/>值
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <param name="serializationType"></param>
|
||
public ByteBlock WriteObject(object value, SerializationType serializationType = SerializationType.RRQMBinary)
|
||
{
|
||
if (value == null)
|
||
{
|
||
this.Write(0);
|
||
return this;
|
||
}
|
||
byte[] data;
|
||
switch (serializationType)
|
||
{
|
||
case SerializationType.RRQMBinary:
|
||
{
|
||
data = SerializeConvert.RRQMBinarySerialize(value);
|
||
}
|
||
break;
|
||
|
||
case SerializationType.Json:
|
||
{
|
||
data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value));
|
||
}
|
||
break;
|
||
|
||
default:
|
||
throw new RRQMException("未定义的序列化类型");
|
||
}
|
||
|
||
this.Write(data.Length);
|
||
this.Write(data);
|
||
return this;
|
||
}
|
||
|
||
#endregion Object
|
||
}
|
||
} |