【问题标题】:How do I marshal an array of bytes to a struct?如何将字节数组编组为结构?
【发布时间】:2009-07-21 15:00:45
【问题描述】:

Related Question

在相关问题中,我试图找出最快的方法。我在那个问题中选择的方法已成为我的瓶颈。我正在从文件中读取一些二进制数据,需要将其放入托管结构定义中。不涉及非托管代码,所以我认为有比分配 GCHandle 更好的方法。

有没有办法将字节数组转换为相同大小的结构?

【问题讨论】:

    标签: c# struct bytearray


    【解决方案1】:

    我有这样的方法:

    static public T ReadStructure<T>(byte[] bytes)
        where T : struct
    {
        int len = Marshal.SizeOf(typeof(T));
        IntPtr i = Marshal.AllocHGlobal(len);
    
        try
        {
            Marshal.Copy(bytes, 0, i, len);
            return (T)Marshal.PtrToStructure(i, typeof(T));
        }
        finally
        {
            Marshal.FreeHGlobal(i);
        }
    }
    

    诚然,它不是很快——但就我而言,它不需要。这是您当前的解决方案吗?您发现分配/复制/释放开销太慢了?

    【讨论】:

    • 我可以试试这个。问题是我必须读取 254 个字节,检查前 240 个字节是否包含类型,如果是则继续。使用这种方法,我从文件中读取数据,将前 240 个字节复制到一个 ptr,检查它,然后将整个 254 复制到一个 ptr。大量复制发生。
    • 听起来有几种优化途径。你能发布一些代码吗?
    • @Ben,相关问题有一个我目前正在做的例子。
    • 由于您是从文件中读取,您可能会考虑 P/Invoking Win32 文件访问方法;您可以将一大块内存分配为 IntPtr,直接读入它,然后直接从其中进行 Marshal,而无需复制到托管字节 [] 缓冲区。
    • 我试过这个。它似乎稍微快一点,而且它肯定使用更少的内存。我看看怎么样,谢谢
    【解决方案2】:

    你可以看看这样的代码:

    struct Foo { public int x; } public unsafe static void Main() { byte[] x = new byte[] { 1, 1, 0, 0 }; Foo f; fixed (byte* xPtr = x) { f = *((Fpp*)xPtr); } Console.WriteLine(f.x); }

    这绝对是非常不安全的,如果结构包含一些更复杂的类型,你可能会遇到问题。

    【讨论】:

    • 跨 32/64 位边界使用此方法有什么影响?有什么方法可以保证在所有可能共享使用此方法存储和读取的数据的机器上完全相似的表示?
    • 什么是 Fpp?当我尝试使用我的类型进行类似声明时,我得到“无法获取托管类型的地址、大小或声明指向托管类型的指针”
    • 我认为他的意思是写 Foo,而不是 Fpp。
    • 是的,应该是 Foo,而不是 Fpp :)。至于 32/64 位边界 - 1. 指针会有一些问题, 2. 默认情况下,c# 中的结构具有顺序布局,所以你不应该对它们有太大的惊喜。 3.你可以使用[StructLayout(Explicit)],随意排列。顺便说一句 - 这种方法不是我用于生产代码的方法,有些地方可能会中断。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    相关资源
    最近更新 更多