gpt4 book ai didi

c# - 将类对象转换为字节并从字节创建对象

转载 作者:太空宇宙 更新时间:2023-11-03 19:05:57 25 4
gpt4 key购买 nike

我已经对这个主题做了一些研究,并在

的帮助下找到了一些解决方案
  1. MemoryStream 和 BinaryFormatter 类
  2. 编码(marshal)级

但是这些方法都不适用于我的类,因为我的类有一个数组。

这是我正在使用的测试类:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class ByteArrayInClass
{
private byte _option;
private ushort _nElements;
private byte[] arrayElements;

public ByteArrayInClass(byte option, ushort nElements)
{
this._option = option;
this._nElements = nElements;
arrayElements = new byte[nElements];
for (int i = 0; i < arrayElements.Length; i++)
{
arrayElements[i] = (byte)i;
}
}

public static byte[] ObjectToBytes(byteArrayInClass value)
{
}

public static byteArrayInClass BytesToObject(byte[] bytes)
{
}
}

主要是:

testObject1 = new ByteArrayInClass(3, 10);
byte[] testBytes1 = ByteArrayInClass.ObjectToBytes(testObject1);

byte[] testBytes2 = { 3, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
ByteArrayInClass testObject2 = ByteArrayInClass.BytesToObjectbyte(testBytes2);

我开始想到我需要将类的成员一个一个地转换为字节,反之将字节转换为对象。有人能给我指出正确的方向吗?

编辑:我对我要做什么还不够清楚。我正在开发一个与服务器通信的程序。它涉及接收数据和发送数据。数据以字节为单位发送和接收,当我接收字节数据时,我需要用接收到的字节构造一个类,这样我就可以理解发送给我的是什么。当我向服务器发送数据时,我首先构造一个具有适当值的类,然后将对象转换为字节,这样我就可以将数据发送到服务器。希望这能更好地解释我正在尝试做的事情。

似乎没有一种简单的方法可以将类转换为字节,所以我自己将每个类成员都转换为字节。所以以下是我想出的。如果这是完成任务的愚蠢方法,请随时告诉我。我想学习一种更聪明的方法来做到这一点。

public static int GetObjectSize(ByteArrayInClass value) 
{
return Marshal.SizeOf(value.Option) + Marshal.SizeOf(value.ElementCount) + (value.ElementCount * 1);
}

public static byte[] ObjectToBytes(ByteArrayInClass value)
{
int copyIndex = 0;
byte[] resultBytes = new byte[GetObjectSize(value)];

resultBytes[copyIndex] = value.Option;
copyIndex += 1;

byte[] elementCountBytes = BitConverter.GetBytes(value.ElementCount);
elementCountBytes.CopyTo(resultBytes, copyIndex);
copyIndex += elementCountBytes.Length;

value.ElementArray.CopyTo(resultBytes, copyIndex);
return resultBytes;
}


public static ByteArrayInClass BytesTObject(byte[] bytes)
{
int convertIndex = 0;
byte option = bytes[convertIndex];
convertIndex += 1;
ushort elementCount = BitConverter.ToUInt16(bytes, convertIndex);
convertIndex += 2;

ByteArrayInClass resultObj = new ByteArrayInClass(option, elementCount);
byte[] elementArray = new byte[elementCount];
int j = 0;
for (int i = convertIndex; i < (convertIndex + elementCount); i++)
{
elementArray[j++] = bytes[i];
}
resultObj.ElementArray = elementArray;
return resultObj;
}

最佳答案

好的,这可能是你要找的

从您的评论和更新中收集到的假设如下

  • 您想要一种通用的方式来序列化您的类(消息)
  • 您希望能够通过网络(套接字,而不是 wcf)使用它
  • 它符合套接字制度
  • 您需要一些基本的反腐败保护措施
  • 您希望它易于使用

注意:这里可能有很多地方可以改进,但这只是给你一些想法

如果您使用类似 web 服务的东西,那么整个答案都是无效的,这实际上只是一种适用于套接字的临时序列化方法

概览

Package 类有以下一些方法

  • 能够将对象序列化为字节
  • 能够将字节反序列化为对象
  • 可以创建带有头信息的包
  • header 包含您的消息类型(选项)
  • 整个包裹的长度
  • 一些基本的校验和和标记,如果出现损坏,您可以验证包

所以给定以下内容

消息枚举

// Some predefined messages
public enum MessageType : byte
{
MyClass,
MyOtherClass,
Message3,
Message4,

}

您想通过网络发送的一些类

// a serilaizable class
// Make this as you like
[Serializable]
public class MyClass
{

public byte[] SomeArbitaryBytes { get; set; }
public string SomeArbitaryString { get; set; }
public int SomeArbitaryInt { get; set; }
public double SomeArbitaryDouble { get; set; }

public MyClass()
{

SomeArbitaryString = "hello";
SomeArbitaryInt = 7;
SomeArbitaryDouble = 98.1;
SomeArbitaryBytes = new byte[10];
for (var i = 0; i < SomeArbitaryBytes.Length; i++)
{
SomeArbitaryBytes[i] = (byte)i;
}
}
}

包类

public static class Package
{
// Method for basic checksum
private static byte GetBasicChecksum(this byte[] data)
{
byte sum = 0;
unchecked // Let overflow occur without exceptions
{
foreach (byte b in data)
{
sum += b;
}
}
return sum;
}

// Serialize to bytes (BinaryFormatter)
public static byte[] SerializeToBytes<T>(this T source)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
return stream.ToArray();
}
}

// Deerialize from bytes (BinaryFormatter)
public static T DeserializeFromBytes<T>(this byte[] source)
{
using (var stream = new MemoryStream(source))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}

// Check if we have enough data
// will throw if it detects a corruption (basic)
// return false if there isnt enough data to determine
// return true and length of the package if sucessfull
public static bool HasValidPackage(this Stream stream, out Int32 messageSize)
{
messageSize = -1;

if (stream.Length - stream.Position < sizeof(byte) * 2 + sizeof(Int32))
return false;


var stx = stream.ReadByte();

if (stx != 2)
throw new InvalidDataException("Invalid Package : STX Failed");

var packageLength = new byte[sizeof(Int32)];
stream.Read(packageLength, 0, sizeof(Int32));
messageSize = BitConverter.ToInt32(packageLength, 0) - sizeof(byte) * 3;
var checkSum = stream.ReadByte();

if (checkSum != packageLength.GetBasicChecksum())
throw new InvalidDataException("Invalid Package : CheckSum Failed");

return stream.Length >= messageSize;

}

// Pack the message
public static byte[] PackMessage<T>(this T source, MessageType messageType)
{
var buffer = source.SerializeToBytes();
var packageLength = BitConverter.GetBytes(buffer.Length + sizeof(byte) * 3);
using (var stream = new MemoryStream())
{
stream.WriteByte(2);
stream.Write(packageLength, 0, sizeof(Int32));
stream.WriteByte(packageLength.GetBasicChecksum());
stream.WriteByte((byte)messageType);
stream.Write(buffer, 0, buffer.Length);
stream.WriteByte(3);
return stream.ToArray();
}
}

// Unpack the message
public static MessageType UnPackMessage(this Stream stream, Int32 messageSize, out byte[] buffer)
{

var messageType = (MessageType)stream.ReadByte();
buffer = new byte[messageSize];
stream.Read(buffer, 0, buffer.Length);

var etx = stream.ReadByte();

if (etx != 3)
throw new InvalidDataException("Invalid Package : ETX Failed");

return messageType;
}

}

客户端代码

// create your class 
var myClass = new MyClass();

// Create a package out of it
var bytes = myClass.PackMessage(MessageType.MyClass);

服务器端代码

// this is server side
using (var stream = new MemoryStream(bytes))
{
Int32 messageSize;

// if we have a valid package do stuff
// this loops until there isnt enough data for a package or empty
while (stream.HasValidPackage(out messageSize))
{

byte[] buffer;

switch (stream.UnPackMessage(messageSize, out buffer))
{
case MessageType.MyClass:
var myClassCopy = buffer.DeserializeFromBytes<MyClass>();
// do stuff with your class
break;
case MessageType.MyOtherClass:
break;
case MessageType.Message3:
break;
case MessageType.Message4:
break;
default:
throw new ArgumentOutOfRangeException();
}

}

// do something with the remaining bytes here, if any, i.e partial package

}

关于c# - 将类对象转换为字节并从字节创建对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27663714/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com