将大端字节集合编组到结构中以提取值

2024-03-23

有一个很有洞察力的问题从字节数组中读取 C# 中的 C/C++ 数据结构 https://stackoverflow.com/questions/2871/reading-a-c-c-data-structure-in-c-from-a-byte-array,但我无法让代码适用于我的大端(网络字节顺序)字节集合。 (编辑:请注意,我的真实结构不仅仅只有一个字段。)有没有一种方法可以将字节编组到结构的大端版本中,然后以框架的字节顺序(主机的字节顺序)提取值,通常是小端)?

(注意,反转字节数组将not工作 - 每个值的字节必须反转,这不会为您提供与反转所有字节相同的集合。)

这应该总结我正在寻找的内容(LE = LittleEndian,BE = BigEndian):

void Main()
{
    var leBytes = new byte[] {1, 0, 2, 0};
    var beBytes = new byte[] {0, 1, 0, 2};
    Foo fooLe = ByteArrayToStructure<Foo>(leBytes);
    Foo fooBe = ByteArrayToStructureBigEndian<Foo>(beBytes);
    Assert.AreEqual(fooLe, fooBe);
}

[StructLayout(LayoutKind.Explicit, Size=4)]
public struct Foo  {
    [FieldOffset(0)] 
    public ushort firstUshort;
    [FieldOffset(2)] 
    public ushort secondUshort;
}

T ByteArrayToStructure<T>(byte[] bytes) where T: struct 
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(T));
    handle.Free();
    return stuff;
}

T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T: struct 
{
    ???
}

其他有用的链接:

结构体的字节以及字节序问题 http://blogs.msdn.com/jeremykuhne/archive/2005/07/19/440264.aspx

有关字节和字节顺序(字节顺序)的更多信息 http://blogs.msdn.com/jeremykuhne/archive/2005/07/21/441247.aspx

使用 C# 更有效地读取二进制文件 http://www.builderau.com.au/architect/webservices/soa/Read-binary-files-more-efficiently-using-C-/0,339024590,320277904,00.htm

不安全并且从文件中读取 http://blogs.msdn.com/ericgu/archive/2004/04/13/112297.aspx

Mono 对这个问题的贡献 http://www.mono-project.com/Mono_DataConvert

掌握 C# 结构 http://www.developerfusion.com/article/84519/mastering-structs-in-c/


这是交换字节序的另一种解决方案。

调整自亚当罗宾逊 https://stackoverflow.com/users/82187/adam-robinson解决方案在这里:https://stackoverflow.com/a/2624377/1254743 https://stackoverflow.com/a/2624377/1254743

它甚至能够处理嵌套结构。

public static class FooTest
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct Foo2
    {
        public byte b1;
        public short s;
        public ushort S;
        public int i;
        public uint I;
        public long l;
        public ulong L;
        public float f;
        public double d;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
        public string MyString;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct Foo
    {
        public byte b1;
        public short s;
        public ushort S;
        public int i;
        public uint I;
        public long l;
        public ulong L;
        public float f;
        public double d;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
        public string MyString;
        public Foo2 foo2;
    }

    public static void test()
    {
        Foo2 sample2 = new Foo2()
        {
            b1 = 0x01,
            s = 0x0203,
            S = 0x0405,
            i = 0x06070809,
            I = 0x0a0b0c0d,
            l = 0xe0f101112131415,
            L = 0x161718191a1b1c,
            f = 1.234f,
            d = 4.56789,
            MyString = @"123456789", // null terminated => only 9 characters!
        };

        Foo sample = new Foo()
        {
            b1 = 0x01,
            s = 0x0203,
            S = 0x0405,
            i = 0x06070809,
            I = 0x0a0b0c0d,
            l = 0xe0f101112131415,
            L = 0x161718191a1b1c,
            f = 1.234f,
            d = 4.56789,
            MyString = @"123456789", // null terminated => only 9 characters!
            foo2 = sample2,
        };

        var bytes_LE = Dummy.StructToBytes(sample, Endianness.LittleEndian);
        var restoredLEAsLE = Dummy.BytesToStruct<Foo>(bytes_LE, Endianness.LittleEndian);
        var restoredLEAsBE = Dummy.BytesToStruct<Foo>(bytes_LE, Endianness.BigEndian);

        var bytes_BE = Dummy.StructToBytes(sample, Endianness.BigEndian);
        var restoredBEAsLE = Dummy.BytesToStruct<Foo>(bytes_BE, Endianness.LittleEndian);
        var restoredBEAsBE = Dummy.BytesToStruct<Foo>(bytes_BE, Endianness.BigEndian);

        Debug.Assert(sample.Equals(restoredLEAsLE));
        Debug.Assert(sample.Equals(restoredBEAsBE));
        Debug.Assert(restoredBEAsLE.Equals(restoredLEAsBE));
    }

    public enum Endianness
    {
        BigEndian,
        LittleEndian
    }

    private static void MaybeAdjustEndianness(Type type, byte[] data, Endianness endianness, int startOffset = 0)
    {
        if ((BitConverter.IsLittleEndian) == (endianness == Endianness.LittleEndian))
        {
            // nothing to change => return
            return;
        }

        foreach (var field in type.GetFields())
        {
            var fieldType = field.FieldType;
            if (field.IsStatic)
                // don't process static fields
                continue;

            if (fieldType == typeof(string)) 
                // don't swap bytes for strings
                continue;

            var offset = Marshal.OffsetOf(type, field.Name).ToInt32();

            // handle enums
            if (fieldType.IsEnum)
                fieldType = Enum.GetUnderlyingType(fieldType);

            // check for sub-fields to recurse if necessary
            var subFields = fieldType.GetFields().Where(subField => subField.IsStatic == false).ToArray();

            var effectiveOffset = startOffset + offset;

            if (subFields.Length == 0)
            {
                Array.Reverse(data, effectiveOffset, Marshal.SizeOf(fieldType));
            }
            else
            {
                // recurse
                MaybeAdjustEndianness(fieldType, data, endianness, effectiveOffset);
            }
        }
    }

    internal static T BytesToStruct<T>(byte[] rawData, Endianness endianness) where T : struct
    {
        T result = default(T);

        MaybeAdjustEndianness(typeof(T), rawData, endianness);

        GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);

        try
        {
            IntPtr rawDataPtr = handle.AddrOfPinnedObject();
            result = (T)Marshal.PtrToStructure(rawDataPtr, typeof(T));
        }
        finally
        {
            handle.Free();
        }

        return result;
    }

    internal static byte[] StructToBytes<T>(T data, Endianness endianness) where T : struct
    {
        byte[] rawData = new byte[Marshal.SizeOf(data)];
        GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
        try
        {
            IntPtr rawDataPtr = handle.AddrOfPinnedObject();
            Marshal.StructureToPtr(data, rawDataPtr, false);
        }
        finally
        {
            handle.Free();
        }

        MaybeAdjustEndianness(typeof(T), rawData, endianness);

        return rawData;
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将大端字节集合编组到结构中以提取值 的相关文章

  • 如何在 DatePicker 上使用 Interactivity:Interaction.Triggers

    我正在尝试将 SelectedDateChanged 绑定到命令 以便我可以将其放置在我的 ViewModel 中 但无论如何它都不会接受此代码 http pastebin com T4q8hQBA http pastebin com T4
  • 为什么连接没有在我的 iSeries/ASP.NET MVC 4 应用程序中重用?

    我们正在 Windows 2008 服务器场上运行 MVC 4 Web 应用程序 我们一直在尝试将服务器场升级到 Windows 2008 R2 64 位服务器 但在 iSeries 运行 V7R1 上遇到了连接池问题 我们经常调用 DB2
  • 将颜色淡化为白色(增加亮度)

    我想用 NET 制作一个文本框 发光 黄色 然后 淡出 为白色 基本上 通过逐渐增加亮度 我认为 Stackoverflow 会在您发布答案后执行此操作 我知道增加亮度并不是那么简单 它不仅仅是均匀地增加 减少 RGB 但我不知道如何做到这
  • 使用 android ndk 独立工具链构建 mono (android ndk r8e)

    我正在尝试使用 android ndk 版本 r8e 中的 ndk 独立工具链构建 mono 但我无法完成构建 我像这样设置我的独立环境 export SYSROOT home jeremybell Desktop android ndk
  • nUnit Assert.That(method,Throws.Exception) 不捕获异常

    有人可以告诉我为什么这个检查异常的单元测试失败了 显然我真正的测试是检查其他代码 但我使用 Int32 Parse 来显示问题 Test public void MyTest Assert That Int32 Parse abc Thro
  • MDI应用程序中父窗体的问题

    我使用按钮作为容器中的控件 父窗体 当子窗体出现时 父窗体中的控件 按钮 图片 标签 出现在子窗体上并将其覆盖 我看不到子窗体 有谁知道如何防止这种情况 我不想将这些控件设置为 Control Visible false 因为当我最小化子表
  • 包含不同类型的两个集合相交

    假设我有一个集合 称之为ids它是类型IEnumerable
  • 降低 Task.Factory.StartNew 线程的优先级

    像下面这样的代码将启动一个新线程来完成这项工作 有什么方法可以控制该线程的优先级吗 Task Factory StartNew gt everything here will be executed in a new thread I wa
  • App.config 连接字符串相对路径

    我需要在 app config 中设置 sqlite 连接字符串 我想设置相对于调试 发布文件夹的路径 数据库文件将复制到这些文件夹
  • 调用 Word.Documents.Add 后 WinWord.exe 不会退出 - Word .NET Interop

    我遇到了一个经典场景 即在 NET 中创建 Word COM 对象 通过 Microsoft Office Interop Word 程序集 时 WinWord 进程不会退出 即使我正确关闭和释放物体 http www xtremevbta
  • 如何将资源添加到现有签名程序集

    鉴于 程序集 例如 SomeLib dll 文本文件 例如 myconfig xml 我需要将文件 myconfig xml 嵌入到现有程序集 SomeLib dll 中 在按 回答 之前请考虑 我知道编译过程中的资源嵌入 csc exe
  • 多种语言如何在一个项目中交互?

    我听说有些人在一个项目中使用多种语言进行编程 我无法想象这些语言如何相互作用 我的意思是没有像这样的Java方法 myProgram callCfunction parameters 从来没有发生过还是我错了 在一个项目中使用多种语言实际上
  • 在具有多个 Web 服务器的现有 .NET / SQL Server 堆栈上实施 Lucene

    我想考虑使用 Lucene 为我当前管理的网站提供全文搜索解决方案 该网站完全基于 SQL Server 2008 C NET 4 技术构建 我要索引的数据实际上非常简单 每个记录只有几个字段 并且只有其中一个字段实际上是可搜索的 我不清楚
  • 您会在新的商业项目中使用 S#arp 架构吗?

    The S arp 架构 http code google com p sharp architecture 看起来真的很酷 但是您是否认为它仍然太新而无法在重要的新项目中做出承诺 我们假设该项目乍一看很适合它 It all seems非常
  • VB.NET:“语句 lambda 无法转换为表达式树”编译时错误

    为什么我可以执行以下操作 Dim qNodes As IQueryable Of XmlNode xDoc ChildNodes AsQueryable Dim test qNodes Where Function node True 尽管
  • .NET类设计问题

    我有一个名为 Question 的类 它有一个名为 Type 的属性 基于这种类型 我想以特定的方式将问题呈现为html 多项选择 单选按钮 多个答案 复选框等 我从一个 RenderHtml 方法开始 该方法根据问题类型调用子方法 但我认
  • 从 Dotnet Google API 获取用户电子邮件信息

    我正在为 gData 和 Drive C API 开发两个独立的 Oauth2 实现 分别将令牌信息存储在 OAuth2Parameters 和 AuthorizationState 中 我可以刷新令牌并将其用于必要的 API 调用 我正在
  • Web API 获取多部分/表单数据响应的最简单方法

    我有问题 但我看不到我做错了什么 我想用最简单的方法来让它工作 稍后我会让它变得更复杂 但目前只想命中 post 方法 我什至不关心里面的代码当前是否正在工作 我唯一关心的是它会发回 OK 200 回复 目前 我要么收到内部服务器错误 50
  • 起订量中的匹配设置问题

    我过去一周左右一直在使用 Moq 直到今天才遇到任何问题 我在获取时遇到问题VerifyAll 以正确匹配我的模拟的设置 我目前正在为我的应用程序的 API 编写单元测试 该应用程序的结构如下 API lt gt Service lt gt
  • 将 VBA 转换为 .NET 语言 [重复]

    这个问题在这里已经有答案了 可能的重复 是否可以将 VBA 转换为 C https stackoverflow com questions 388819 is it possible to convert vba to c 假设我有一个大型

随机推荐