2017-03-08 91 views
4

我嘗試解析一個字節數組結構,但它不適用於Sequential。 Sequential結構中的值是錯誤的,但它對Explicit結構是否正確?我需要順序的字節數組沒有固定的長度。 DwLength字段是數據字段的大小。C#解析字節結構順序

  • 消息類型128(順序128)
  • DwLength 20(順序33554432)
  • 插槽0(順序0)
  • SEQ 0(順序0)
  • 狀態2(順序59)
  • 錯誤0(順序143)
  • ChainParameter 0(順序128)

測試代碼

var bytes = new byte[] { 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3B, 0x8F, 0x80, 0x01, 0x80, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x68 }; 

var result1 = GetStruct<RdrToPcDataBlock1>(bytes); 
var result2 = GetStruct<RdrToPcDataBlock2>(bytes); 

結構RdrToPcDataBlock序貫

[StructLayout(LayoutKind.Sequential)] 
public struct RdrToPcDataBlock1 
{ 
    public byte MessageType; 
    public int DwLength; 
    public byte Slot; 
    public byte Seq; 
    public byte Status; 
    public byte Error; 
    public byte ChainParameter; 
    [MarshalAs(UnmanagedType.ByValArray)] 
    public byte[] Data; 
} 

結構RdrToPcDataBlock顯式

[StructLayout(LayoutKind.Explicit)] 
public struct RdrToPcDataBlock2 
{ 
    [FieldOffset(0)] 
    public byte MessageType; 
    [FieldOffset(1)] 
    public int DwLength; 
    [FieldOffset(5)] 
    public byte Slot; 
    [FieldOffset(6)] 
    public byte Seq; 
    [FieldOffset(7)] 
    public byte Status; 
    [FieldOffset(8)] 
    public byte Error; 
    [FieldOffset(9)] 
    public byte ChainParameter; 
    [FieldOffset(10)] 
    public byte Data; 
} 

GetStruct

public T GetStruct<T>(byte[] bytes) 
{ 
    try 
    { 
     var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     var item = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
     handle.Free(); 
     return item; 
    } 
    catch 
    { 
     return default(T); 
    } 
} 
+0

_「值是錯誤的_」 - 請更具體。 _「錯」_以什麼方式?你會得到什麼結果?你期望的結果是什麼?請提供一個可靠地再現問題的良好[mcve],並更準確地解釋問題。還要注意''LayoutKind.Sequential'受制於包裝規則,所以不符合的字段可能不會達到您的預期。 (我現在沒有時間去查看它,但是我不相信即使你可以使用'LayoutKind.Sequential'工作,你也會得到你想要的結果,也就是說在最後填充一個數組對象與多餘的數據。) –

+0

你將不得不使用自定義編組器。否則,你不能處理可變長度的數組。以下是一個示例:http://stackoverflow.com/a/38884095/103959 –

回答

5

這樣做[StructLayout(LayoutKind.Sequential)]是一樣做[StructLayout(LayoutKind.Sequential, Pack=0)]這將使用默認的填料的過程的位數(4用於32位和8爲64位)。爲了讓您想讓你需要明確地說,你不希望任何填充通過設置[StructLayout(LayoutKind.Sequential, Pack=1)]

更新行爲:你仍然要與你的可變長度的字節數組中運行的問題。請參閱comment by Jean-Bernard Pellerin

您將不得不使用自定義編組器。否則,你不能處理可變長度的數組。這裏有一個例子:https://stackoverflow.com/a/38884095/103959