具有字节字段的结构与byte[]相匹配
本文关键字:byte 字节 字段 结构 | 更新日期: 2023-09-27 17:50:54
我有一个如下的结构
private struct MessageFormat
{
public byte[] Header; //start of message
public byte Fragmentation; //single packet or not
public byte Encryption; //encrypted message
public byte[] Authentication; //password
public byte[] Flag; //to locate end of auth
public byte[] Data; //info
public byte[] Trailer; //end of message
}
是否有一个方便的方法来转换整个MessageFormat成一个单字节数组[]后,我填充所有的字段?
我已经编写了一个示例代码,它将完全满足您的要求。它结合了反射和Buffer.BlockCopy
,但它可以做得更好(例如,提前封装format
,避免匿名类型——以及它们在示例中尴尬的、冗余的初始化——或者甚至根本不使用反射并硬编码序列化方法)。请注意,我提供的方法不为结果使用缓冲区,而是在分配数组之前计算最终长度。
var format = new MessageFormat
{
//Initialize your format
};
//Gets every instance public field in the type
//Expects it to be either byte, either byte[]
//Extracts value, length and type
var fields = typeof (MessageFormat).GetFields().
Select(f => f.GetValue(format)).
Select(v => new
{
Value = v,
Type = v is byte ? typeof (byte) : typeof (byte[]),
Length = v is byte ? 1 : (v as byte[]).Length
}).
ToArray();
//Calculates the resulting array's length
var totalLength = fields.Sum(v => v.Length);
var bytes = new byte[totalLength];
var writingIndex = 0;
foreach (var field in fields)
{
//If the field is a byte, write at current index,
//then increment the index
if (field.Type == typeof (byte))
bytes[writingIndex++] = (byte) field.Value;
else
{
//Otherwise, use a performant memory copy method
var source = field.Value as byte[];
var sourceLength = source.Length;
Buffer.BlockCopy(source, 0, bytes, writingIndex, sourceLength);
writingIndex += sourceLength;
}
}
每个字节数组实际上存储了对字节数组的引用,因此它不是直接的单个数组。
您需要从这些数据中构建一个数组。我会,个人,使方法做到这一点,创建相应长度的byte[]
,然后使用数组。
有很多方法,但都需要逐个字段地提取字节。
这是一个:
var msg = new MessageFormat();
var arr = new byte[msg.Header.Length + 1 + 1 + msg.Authentication.Length + msg.Flag.Length + msg.Data.Length + msg.Trailer.Length];
using (var stream = new MemoryStream(arr, 0, arr.Length, true))
{
stream.Write(msg.Header, 0, msg.Header.Length);
stream.WriteByte(msg.Fragmentation);
stream.WriteByte(msg.Encryption);
stream.Write(msg.Authentication, 0, msg.Authentication.Length);
stream.Write(msg.Flag, 0, msg.Flag.Length);
stream.Write(msg.Data, 0, msg.Data.Length);
stream.Write(msg.Trailer, 0, msg.Trailer.Length);
}
您也可以使用Buffer.BlockCopy
或Array.Copy
。