简体   繁体   English

Python 在.Net 中的打包/解包

[英]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?是否有任何 function 等效于 Python 的 struct.pack 和 C# 中的trigger.unpack 允许我像这样打包和解包值?

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).您必须使用BinaryWriter或带有BitConverterMemoryStream或新的BinaryPrimitives以及可能由byte[]支持的Span<>手动完成(但它更复杂......您必须知道结果宽度开始写入之前的缓冲区,而MemoryStream正在自动放大)。

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.更糟糕的是:.NET 使用多类型数组(每个元素都可以是任何类型的数组),就像unpack返回的那样有点不受欢迎,而且性能低下。 You have to use a object[] , so you'll box every element.您必须使用object[] ,因此您将装箱每个元素。

Now... Manually "serializing" to binary is quite easy (even if much longer than Python):现在......手动“序列化”为二进制非常容易(即使比 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}")));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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