Reputation: 13140
So I have a gigantic byte-array that represents a data packet. There's various parts of the packet such as a header, message body, stop bits, etc. How can I create variables of the various parts of the array such that when I reference the variable I'm editing the sub-array? I'd like to use the dot notation so that referencing ByteArrayRepresentingPacket.Header
would actually reference ByteArrayRepresentingPacket[0]
, ByteArrayRepresentingPacket.MessageBody
would actually reference ByteArrayRepresentingPacket[1]
through ByteArrayRepresentingPacket[8]
, etc. A structure seems suited for this, but how would I translate the structure into a byte-array when I need to pass it?
Upvotes: 0
Views: 697
Reputation: 13140
So I ended up going with a structure (like I had hoped I could). Here's the implementation:
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(); }
}
}
I kept everything as IEnumerable
so that I could just use LINQ's .Concat
operator (to make everything clean & concise). What I'm unsure of is if the performance savings I gain from using a struct (no boxing/unboxing) will be undone by using IEnumerable
Properties and LINQ
Upvotes: 0
Reputation: 20180
You're better off not worrying about forcing your packet structure to be stored as a byte array. The CPU cost of converting to and from a byte array, and the memory costs of the temporary duplicate storage are most likely insignificant. Create a class or set of classes to represent your data structure, and then use BinaryWriter
to convert it to a byte array in the format required by your protocol.
If you really want to use a structure, look into the Marshal.StructureToPtr
method, and the [LayoutKind]
and [MarshalAs]
attributes. But be warned, if your data structure contains an variable length fields (strings or arrays), you won't be able to convert it to a byte array using this method. And I don't see any reason why you should go this route. It's really intended for Win32 interop.
EDIT:
Another thought, if you were stuck with a big byte array, and you really wanted to access chunks of it by name, I would create an implementation of IList<T>
that took a T[]
an offset and a length, and just used the array as its storage. Then you could create a class like so:
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
}
Upvotes: 3
Reputation: 458
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;
}
}
Upvotes: 1