C#結構體和字節數組的轉換函數


在通信過程中,一般我們都會操作到字節數組.特別是希望在不同語言編程進行操作的時候.

雖然C#提供了序列化的支持,不用字節數組也行.但操作字節數組肯定會碰到.
 
一般都會采用結構來表示字節數組.但結構與字節數組直接的轉換實在很麻煩.
字節操作不但容易出錯,而且每增加一個結構,就自己實現一遍,實在是煩不勝煩.
 
有沒有簡單的方法呢?當然有.可以采用非托管區的一些方法來實現.
 
首先,導入命名空間:System.Runtime.InteropServices;
 
定義結構的時候,要給結構指定特性.
 
如:
     //注意這個特性不能少
     [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
     struct TestStruct
     {
         public int c;
         //字符串,SizeConst為字符串的最大長度
         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
         public string str;
         //int數組,SizeConst表示數組的個數,在轉換成
         //byte數組前必須先初始化數組,再使用,初始化
         //的數組長度必須和SizeConst一致,例test = new int[6];
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
         public int[] test;
        
     }
 
你可以修改特性的屬性,來更改在內存的布局和排列.
 
好,接下來將結果轉換為字節數據.為了支持各種結構,我采用泛型的做法.這樣編譯器可以幫助我們檢查類型是否正確.
 
   ///
         /// 結構體轉byte數組
         ///
         /// 要轉換的結構體
         /// 轉換后的byte數組
         public static byte[] StructToBytes(T structObj)where T:struct
         {
             //得到結構體的大小
             int size = Marshal.SizeOf(structObj);
             //創建byte數組
             byte[] bytes = new byte[size];
             //分配結構體大小的內存空間
             IntPtr structPtr = Marshal.AllocHGlobal(size);
             //將結構體拷到分配好的內存空間
             Marshal.StructureToPtr(structObj, structPtr, false);
             //從內存空間拷到byte數組
             Marshal.Copy(structPtr, bytes, 0, size);
             //釋放內存空間
             Marshal.FreeHGlobal(structPtr);
             //返回byte數組
             return bytes;
         }
 
將字節數組轉換為指定結構
 
         ///
         /// byte數組轉結構體
         ///
         /// byte數組
         /// 轉換后的結構體
         public static T BytesToStuct(byte[] bytes)where T:struct
         {
             T type = new T();
             
             //得到結構體的大小
             int size = Marshal.SizeOf(type);
             //byte數組長度小於結構體的大小
             if (size > bytes.Length)
             {
                 //返回空
                 return (default (T));
             }
             //分配結構體大小的內存空間
             IntPtr structPtr = Marshal.AllocHGlobal(size);
             //將byte數組拷到分配好的內存空間
             Marshal.Copy(bytes,0,structPtr,size);
             //將內存空間轉換為目標結構體
             object obj = Marshal.PtrToStructure(structPtr, type.GetType ());
             //釋放內存空間
             Marshal.FreeHGlobal(structPtr);
             //返回結構體
             return (T)obj;
         }
 
雖然我對T類型進行了限制,但如果結構沒有指定特性的話,運行不會出現問題,但邏輯可能會出現一些問題,出現了你不想要的結果.這是必須注意的.
 
那怎么使用這些代碼呢?
 
         public static void TestC()
         {
             TestStruct t = new TestStruct();
             t.c = 100;
             t.str = "12345";
             t.test = new int[] { 1, 2, 5, 6, 9,4 };
 
             byte[] data = StructToBytes(t);
             foreach (var item in data)
             {
                 Console.WriteLine(item);
             }
 
             TestStruct tm = BytesToStuct(data);
 
             Console.WriteLine("C:{0} str={1}",tm.c,tm.str );
             foreach (var item in tm.test)
             {
                 Console.WriteLine(item);
             }
 
         }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM