所以我有一个代表数据包的巨大字节数组。包的各个部分,如标题,消息体,停止位等。如何创建数组各个部分的变量,以便在我引用变量时我正在编辑子数组?我想使用点符号,以便引用ByteArrayRepresentingPacket.Header
实际引用ByteArrayRepresentingPacket[0]
,ByteArrayRepresentingPacket.MessageBody
实际引用ByteArrayRepresentingPacket[1]
到ByteArrayRepresentingPacket[8]
等。结构看起来很适合这个,但是当我需要传递它时,如何将结构转换为字节数组呢?
答案 0 :(得分:3)
最好不要担心强制将数据包结构存储为字节数组。转换到字节数组和从字节数组转换的CPU成本以及临时重复存储的内存成本很可能是微不足道的。创建一个或一组类来表示您的数据结构,然后使用BinaryWriter
将其转换为协议所需格式的字节数组。
如果您确实想要使用结构,请查看Marshal.StructureToPtr
方法以及[LayoutKind]
和[MarshalAs]
属性。但请注意,如果您的数据结构包含可变长度字段(字符串或数组),则无法使用此方法将其转换为字节数组。而且我认为你不应该走这条路。它真的适用于Win32互操作。
修改强>
另一个想法,如果你遇到一个大字节数组,并且你真的想按名称访问它的块,我会创建一个IList<T>
的实现,它带有T[]
个偏移量一个长度,只是使用数组作为其存储。然后你可以像这样创建一个类:
public class Packet
{
public byte[] PacketData;
public SubArray<byte> Header;
public SubArray<byte> MessageBody;
// Add more SubArrays for each of the remainder of your 8 packet pieces
//modify this constructor as needed
public Packet(byte[] data)
{
// replace the offsets and lengths here with appropriate data
Header = new SubArray<byte>(data, 0, 10);
MessageBody = new SubArray<byte>(data, 10, 100);
}
}
public class SubArray<T> : IList<T>
{
private T[] data;
private int offset;
private int length;
public SubArray(T[] data, int offset, int length)
{
this.data = data;
this.offset = offset;
this.length = length;
}
public T this[int i]
{
get
{
if (i < 0 || i >= length) throw new ArgumentOutOfRangeException();
return data[i + offset];
}
set
{
if (i < 0 || i >= length) throw new ArgumentOutOfRangeException();
data[i + offset] = value;
}
}
// TODO: Implement the rest of IList<T> accordingly
}
答案 1 :(得分:1)
public class Packet
{
public byte[] Header;
public byte[] MessageBody;
// Add a single-dimensional byte array for each of the remainder of your 8 packet //pieces
//modify this constructor as needed
public Packet(byte[] header, byte[] messageBody[])
{
Header = header;
MessageBody = messageBody;
}
public byte[][] ToArray()
{
byte[][] byteArray = new byte[8][];
byteArray[0] = Header;
byteArray[1] = MessageBody;
// The rest of your 8 go here
return byteArray;
}
}
答案 2 :(得分:0)
所以我最终选择了一个结构(就像我希望的那样)。这是实施:
public struct Packet
{
/// <summary>
/// Constructor for initializing packet
/// </summary>
/// <param name="header"></param>
/// <param name="message"></param>
public Packet(byte[] header, byte[] message)
: this()
{
this.Header = header;
this.Message = message;
}
// Properties representing each part of the sub-packet parts (can be made private if needed)
public IEnumerable<byte> Header { get; set; }
public IEnumerable<byte> Message { get; set; }
public IEnumerable<byte> StopBit { get { return new byte[1] { 0xFF }; } }
/// <summary>
/// Returns the byte representation of the whole packet
/// </summary>
public byte[] GetBytes
{
get { return Header.Concat(Message).Concat(StopBit).ToArray(); }
}
}
我将所有内容保留为IEnumerable
,以便我可以使用LINQ的.Concat
运算符(使所有内容变得干净简洁)。我不确定的是,通过使用IEnumerable
属性和LINQ