简体   繁体   中英

Python's pack/unpack in .Net

Is there any function equivalent to Python's struct.pack and struck.unpack in C# that allows me to pack and unpack values like this?

Check out struct Library.

There's an unpack method similar to what you've posted in the image

 struct.pack(format, v1, v2, ...)

    Return a bytes object containing the values v1, v2, … packed according to the format string format. The arguments must match the values required by the format exactly

No, there isn't. You'll have to do it manually with a BinaryWriter , or a MemoryStream with BitConverter or the new BinaryPrimitives plus a Span<> supported probably by a byte[] (but it is more complex... You have to know the resulting width of the buffer before you begin to write, while the MemoryStream is auto-enlarging).

It gets even worse: with .NET using a multi-type array (an array where every element can be of any type) like the one returned by unpack is a little frowned upon, and it is low performance. You have to use a object[] , so you'll box every element.

Now... Manually "serializing" to binary is quite easy (even if much longer than Python):

byte command_type = 1;
byte command_class = 5;
byte command_code = 0x14;
int arg0 = 0;
int arg1 = 0;

// We know the message plus the checksum has length 12
var packedMessage2 = new byte[12];

// We use the new Span feature
var span = new Span<byte>(packedMessage2);

// We can directly set the single bytes
span[0] = command_type;
span[1] = command_class;
span[2] = command_code;

// The pack is <, so little endian. Note the use of Slice: first the position (3 or 7), then the length of the data (4 for int)
BinaryPrimitives.WriteInt32LittleEndian(span.Slice(3, 4), arg0);
BinaryPrimitives.WriteInt32LittleEndian(span.Slice(7, 4), arg1);

// The checksum
// The sum is modulo 255, because it is a single byte.
// the unchecked is normally useless because it is standard in C#, but we write it to make it clear
var sum = unchecked((byte)packedMessage2.Take(11).Sum(x => x));

// We set the sum
span[11] = sum;

// Without checksum
Console.WriteLine(string.Concat(packedMessage2.Take(11).Select(x => $@"\x{x:x2}")));

// With checksum
Console.WriteLine(string.Concat(packedMessage2.Select(x => $@"\x{x:x2}")));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM