首页 > 系统相关 >034-MemoryStream内存数据读写

034-MemoryStream内存数据读写

时间:2022-12-06 12:11:11浏览次数:54  
标签:arr MemoryStream 读写 value base BitConverter byte public 034

位与字节

计算机中最小的单位时“位”,用bit表示,数据是用二进制来表示。但是bit过小,因此用字节来作为存储单位,用“Byte”表示,其中8位组成一个字节。所以一个字节表示的数的范围是0到255。
例如int数据类型有四个字节也就是32位,但是int数据有正负的区别,因此用第一位来表示数据的正负,剩下31位来表示数据,所以int数据类型表示的范围是±(2^31 - 1);而uint数据类型没有正负之分,所以32位全部用来表示数据大小,所以uint数据类型表示的范围是(2^32 - 1)。

核心读写类的编写

在mmorpg游戏中,关于游戏的传输,读写保存可以采用很多种格式,现在比较常见的有使用json或xml格式来保存传输数据,但是也有效率更高的方式,就是将游戏中的类和数据转换为字节数组来传输存储,下面是核心类的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using System.Text;

/// <summary>
/// 数据转换(byte,short,int,long,float,decimal,bool,string)
/// </summary>
public class MMO_MemoryStream : MemoryStream
{
    public MMO_MemoryStream() { }

    public MMO_MemoryStream(byte[] buffer) : base(buffer) { }

    #region short
    /// <summary>
    /// 从流中读取一个short数据
    /// </summary>
    /// <returns></returns>
    public short ReadShort()
    {
        byte[] arr = new byte[2];
        base.Read(arr, 0, 2);
        return BitConverter.ToInt16(arr, 0);
    }

    /// <summary>
    /// 把一个short数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteShort(short value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region ushort
    /// <summary>
    /// 从流中读取一个ushort数据
    /// </summary>
    /// <returns></returns>
    public ushort ReadUShort()
    {
        byte[] arr = new byte[2];
        base.Read(arr, 0, 2);
        return BitConverter.ToUInt16(arr, 0);
    }

    /// <summary>
    /// 把一个ushort数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteUShort(ushort value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region int
    /// <summary>
    /// 从流中读取一个int数据
    /// </summary>
    /// <returns></returns>
    public int ReadInt()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);
        return BitConverter.ToInt32(arr, 0);
    }

    /// <summary>
    /// 把一个int数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteInt(int value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region uint
    /// <summary>
    /// 从流中读取一个UInt数据
    /// </summary>
    /// <returns></returns>
    public uint ReadUInt()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);
        return BitConverter.ToUInt32(arr, 0);
    }
    /// <summary>
    /// 把一个UInt数据写入流
    /// </summary>
    public void WriteUInt(uint value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region long
    /// <summary>
    /// 从流中读取一个long数据
    /// </summary>
    /// <returns></returns>
    public long ReadLong()
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);
        return BitConverter.ToInt64(arr, 0);
    }
    /// <summary>
    /// 将一个long数据写入流中
    /// </summary>
    /// <param name="value"></param>
    public void WriteLong(long value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region ulong
    /// <summary>
    /// 从流中读取一个ulong数据
    /// </summary>
    /// <returns></returns>
    public ulong ReadULong()
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);
        return BitConverter.ToUInt64(arr, 0);
    }
    /// <summary>
    /// 将一个ulong数据写入流中
    /// </summary>
    /// <param name="value"></param>
    public void WriteULong(ulong value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    #endregion

    #region float
    /// <summary>
    /// 从流中读取一个float数据
    /// </summary>
    /// <returns></returns>
    public float ReadFloat()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);
        return BitConverter.ToSingle(arr, 0);
    }
    /// <summary>
    /// 将一个float数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteFloat(float value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }
    #endregion

    #region double
    /// <summary>
    /// 从流中读取一个double数据
    /// </summary>
    /// <returns></returns>
    public double ReadDouble() 
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);
        return BitConverter.ToDouble(arr, 0);
    }
    /// <summary>
    /// 将一个double数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteDouble(double value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    #endregion

    #region bool
    /// <summary>
    /// 从流中读取一个bool数据
    /// </summary>
    /// <returns></returns>
    public bool ReadBool()
    {
        return base.ReadByte() == 1;
    }
    /// <summary>
    /// 将一个bool数据写入流
    /// </summary>
    /// <param name="value"></param>
    public void WriteBool(bool value)
    {
        byte[] arr = new byte[1];
        arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, 1);
        //base.WriteByte((byte)(value == true ? 1 : 0));
    }
    #endregion

    #region UTF8String
    /// <summary>
    /// 从流中读取一个UTF8字符串数据
    /// </summary>
    /// <returns></returns>
    public string ReadUTF8String()
    {
        ushort len = this.ReadUShort();
        byte[] arr = new byte[len];
        base.Read(arr, 0, len);
        return Encoding.UTF8.GetString(arr);
    }
    /// <summary>
    /// 将一个string数据写入流
    /// </summary>
    /// <param name="str"></param>
    public void WriteUTF8String(string str)
    {
        byte[] arr = Encoding.UTF8.GetBytes(str);
        if (arr.Length > 65535)
        {
            throw new InvalidCastException("字符串超出范围");
        }
        WriteUShort((ushort)arr.Length);
        base.Write(arr, 0, arr.Length);
    }
    #endregion
}

使用方法

在使用时可以通过下列方法来使用

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestMemory : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //byte[] arr = BitConverter.GetBytes(1);
        ////for (int i = 0; i < arr.Length; i++)
        ////{
        ////    Debug.Log(i + ":" + arr[i]);
        ////}
        //Debug.Log(BitConverter.ToBoolean(arr, 0));
        Item item = new Item() { Id = 1, Name = "黑皇杖" };
        byte[] arr = null;
        using(MMO_MemoryStream ms = new MMO_MemoryStream())
        {
            ms.WriteInt(item.Id);
            ms.WriteUTF8String(item.Name);
            arr = ms.ToArray();
        }
        //if(arr.Length > 0)
        //{
        //    for (int i = 0; i < arr.Length; i++)
        //    {
        //        Debug.Log(i + ":" + arr[i]);
        //    }
        //}
        int id = 0;
        string name = null;
        using(MMO_MemoryStream ms = new MMO_MemoryStream(arr))
        {
            id = ms.ReadInt();
            name = ms.ReadUTF8String();
        }
        Debug.Log(id);
        Debug.Log(name);
    }

}

public class Item
{
    public int Id;
    public string Name;
}

标签:arr,MemoryStream,读写,value,base,BitConverter,byte,public,034
From: https://www.cnblogs.com/AlexNJW/p/16954807.html

相关文章

  • [C++11与并发编程]读写锁的简单实现
    读写锁的简单实现layout:posttitle:读写锁categories:cpp_concurrencydescription:C++并发编程简介keywords:c++,并发编程,读写锁​​boost共享锁实现​​​读写......
  • C++读写二进制文件
    方法一:#include<stdio.h>#include<stdlib.h>#include<fstream>#include<string>//size_treadBinaryFile(constchar*filename,unsignedchar*&data){......
  • Linux 下 hwclock 读写 RTC 报错 Invalid argument
    以上错误信息都是因为year设置不当引起的。没有设置RTC,RTC也不会启动计时。下面首先设置正确的系统时间,然后将系统时间传递给RTC。tm里的tm_year是从1900年开始算的,如要......
  • CSV:CSV文件的读写库
    CSV格式的全称是CommaSeparatedValues,意思是逗号分割的数据,是最常见的电子表格和数据库的导出格式之一,在RFC4180中已经成为了一种标准格式。Python中提供了一个官......
  • Mysql主从复制,读写分离
    一、Mysql主从复制概述在企业中,业务数据量通常都比较大,单台Mysql在安全性,高可用性和高并发方面都无法满足实际需求,因此可以通过主从复制的方式来同步数据,再通过读写分离来提......
  • MYSQL主从复制与读写分离
    一、MySQL主从复制的理论部分1.1mysql支持的复制类型STATEMENT∶基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效......
  • MYSQL主从复制与读写分离
    一、MySQL主从复制与读写分离1.1主从分离和读写分离的相关概述1)主从复制与读写分离在实质际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实院需求......
  • WPF 读写自定义配置文件
    程序集如下usingSystem.Windows;namespaceWpfApp1{///<summary>///MainWindow.xaml的交互逻辑///</summary>publicpartialclassMainW......
  • 三阶段:第15周 读写分离、分库分表
           ......
  • Microsoft.IO.RecyclableMemoryStream源码解读
    一、RecyclableMemoryStreamManager源码地址:https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream小对象池和大对象池管理、RecyclableMemoryStream创建、......