【问题标题】:How do I convert byte array to UInt32 array?如何将字节数组转换为 UInt32 数组?
【发布时间】:2011-09-02 20:28:15
【问题描述】:

假设在 C++ 中我得到了这样的代码..

void * target
uint32 * decPacket = (uint32 *)target;

所以在 C# 中它会像..

byte[] target;
UInt32[] decPacket = (UInt32[])target;

无法将类型 byte[] 转换为 uint[]

如何将 C++ 执行的内存对齐操作转换为 C# 数组?

【问题讨论】:

标签: c# arrays bytearray uint32


【解决方案1】:

好吧,使用Buffer.BlockCopy

uint[] decoded = new uint[target.Length / 4];
Buffer.BlockCopy(target, 0, decoded, 0, target.Length);

请注意,BlockCopy 的最后一个参数始终是要复制的字节数,无论您要复制的类型如何。

在 C# 中,您不能只将 byte 数组视为 uint 数组(至少不是在安全代码中;我不知道在不安全代码中) - 但 Buffer.BlockCopy 会溅出将byte 数组放入uint 数组中...根据系统的字节顺序确定结果。就我个人而言,我喜欢这种方法——当您迁移到具有不同内存布局的系统时,它会使代码很容易出错。我更喜欢在我的协议中明确。但希望它会在这种情况下对您有所帮助。

【讨论】:

  • 对我有帮助,是的。似乎在 C++ 中它从不复制任何东西.. 它只是一次从字节扫描重新对齐到两个字节。至少这个解决方案避免了我使用循环来完成这个过程。
  • 在不安全的代码中,你可以这样做——你可以修复数组并使用指针数学直接遍历字节数组作为 uint 指针。它运作良好,但它基本上恢复到 C/C++/native 方法...
【解决方案2】:

如果你愿意走向黑暗面,你可以吃蛋糕(避免分配)并吃掉它(避免迭代)。

查看我对相关问题的回答,我在其中演示了如何将 float[] 转换为 byte[],反之亦然:What is the fastest way to convert a float[] to a byte[]?

【讨论】:

    【解决方案3】:

    As Jon mentioned,Buffer.BlockCopy 可以很好地复制这个。

    但是,如果这是一个互操作场景,并且您想以 uint[] 的身份直接访问字节数组,那么您可以做的最接近 C++ 的方法是使用不安全的代码:

    byte[] target;
    CallInteropMethod(ref target);
    
    fixed(byte* t = target)
    {
       uint* decPacket = (uint*)t;
    
       // You can use decPacket here the same way you do in C++
    }
    

    我个人更喜欢制作副本,但如果您需要避免实际复制数据,这确实可以让您工作(在不安全的环境中)。

    【讨论】:

    • 哇太棒了!..我得试试这个!什么是? CallInteropMethod
    • @SSpoke:在不安全的上下文中,C# 的行为与 C++ 非常相似 - 并得到所有指针的好坏处;)
    • CallInteropMethod 只是在说“这是要填充字节 [] 的东西” - 通常,这不会在纯托管代码中使用...
    • Blah 我想了想.. 我厌倦了 C++.. 这就是为什么我将它移植到 .NET.. 所以我会严格保留它 C#.. 没有任何不安全的代码。 (老实说,我很困惑:P 我必须将所有的括号括起来我的所有逻辑?然后我还有 encPacket 这也是字节 - > uint32 等等太复杂了呵呵
    • @SSpoke:良好的调用(除非这是性能。关键代码) - 我通常会在所有情况下避免这种情况,除了那些我已经分析并发现它非常非常难以处理的情况重大影响。
    【解决方案4】:

    您可以使用Buffer.BlockCopyBlockCopy 不是Array.Copy,而是在不检查数组类型是否完全兼容的情况下进行字节级复制。

    像这样:

    uint[] array = new uint[bytes.Length/4];
    Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length);
    

    【讨论】:

    • 我很确定如果你这样做,你会得到一个例外。 "偏移量和长度超出数组的范围或计数大于从索引到源集合末尾的元素数"
    • 为什么? BlockCopy 的参数长度以字节为单位。
    【解决方案5】:

    我使用了 BitConverter.ToUInt32() - https://docs.microsoft.com/en-us/dotnet/api/system.bitconverter.touint32?view=netcore-3.1

    byte[] source = new byte[n];
    UInt32 destination;
    
    destination = BitConverter.ToUInt32(source, 0);
    

    这对我来说似乎很好用。

    【讨论】:

      【解决方案6】:

      遍历所有数组项并在每个数组项上调用 Convert.ToUint32()。这里:

       Uint32[] res = new Uint32[target.Length];
       for(int i = 0;i <= target.Length;i++) 
       {
           res[i] = Convert.ToUint32(target[i]);
       }
      

      这是来自 MSDN 的官方链接。 http://msdn.microsoft.com/en-us/library/469cwstk.aspx

      【讨论】:

      • 这还能用吗?如果有字节,它将创建尽可能多的UInt32。不过,我必须将 2 个字节转换为 1 uint
      • 我认为new Uint32[target.length] 必须是new Uint32[target.length / sizeof(UInt32)]
      • 如果你想循环,这需要使用 BitConverter。这将为您提供一个包含单个字节值的单位 - 这是非常不同的......
      • 如果您确定这是正确的@SSpoke,请随时编辑。我总是愿意为愿意纠正我的错误的人开放。
      猜你喜欢
      • 2019-10-18
      • 2021-08-20
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 2012-07-11
      相关资源
      最近更新 更多