2012-12-26 32 views
1

我正在開發一個C#應用程序,它讀取二進制文件的內容並在datagrid視圖中顯示相同的內容。該數據的格式是這樣的字節數組轉換的動態結構

[StructLayout(LayoutKind.Sequential)] 
public class sProtParElement 
{ 
    public ushort wNameIndex; 
    public eDataTypeTag eDataType; //eDataTypeTag is an enum 
    public ushort wLen; 
    public Data_Variant_tag Vt_Var; //Data_Variant_tag is a struct 
} 

其中,

[StructLayout(LayoutKind.Explicit)] 
public struct Data_Variant_tag 
{ 
    [FieldOffset(0)]public byte yVal; 
    [FieldOffset(0)]public sbyte cVal; 
    [FieldOffset(0)]public ushort wVal; 
    [FieldOffset(0)]public short iVal; 
    [FieldOffset(0)]public uint xVal; 
    [FieldOffset(0)]public int lVal; 
    [FieldOffset(0)]public IntPtr pcVal; 
} 

現在,用戶可以從數據網格視圖數據的變化,並保存在緩衝區中更新的數據,以便它可以再次寫回文件。

我面對的問題是因爲數據類型不同。當我想將內容寫回字節數組時,我簡單地不能使用固定的結構體大小,因爲我遇到了不同的數據類型大小。

有人能告訴我如何創建一個動態緩衝區,並在字節緩衝區中只寫入所需的數據大小?

回答

0

您需要分配新的緩衝區。修改後的結構之前的所有數據必須按照原樣複製。修改後的緩衝區之後的所有數據都必須移位。你可以使用System.Buffer這個類。

2

可以使用Marshal類結構與明確順序佈局轉換爲字節數組。

var element = new sProtParElement() 
{ 
    wLen = 1, 
    wNameIndex = 2, 
    Vt_Var = new Data_Variant_tag { lVal = 3 } 
}; 

var size = Marshal.SizeOf(element); 
var buffer = new byte[size]; 
IntPtr ptr = IntPtr.Zero; 
try 
{ 
    ptr = Marshal.AllocHGlobal(size); 
    Marshal.StructureToPtr(element, ptr, true); 
    Marshal.Copy(ptr, buffer, 0, size); 
} 
finally 
{ 
    Marshal.FreeHGlobal(ptr); 
} 
0

感謝您的回覆。我使用了與Lambda表達式結合的泛型來實現我的解決方案。

由於在結構中的成員是基於所述數據類型不同的尺寸,我創建字節陣列的列表,其已持有數據網格視圖

的所有元件現在每次,用戶進行的改變在數據網格視圖中,我創建了一個臨時緩衝區,並僅覆蓋原始緩衝區內容,例如

   byte[] modifiedArray = 
      GenerateByteArrayFromPPDataList(e.RowIndex,newPPDataList[e.RowIndex].eDataType); 

     listofArrays[e.RowIndex] = modifiedArray; //listofArrays[e.RowIndex] -> byte array at index position e.RowIndex 

然後我使用lambda表達式向量化這個列表。我使用了從stackoverflow的例子來做到這一點。

/// <summary> 
    /// Converst the list of byte arrays which contains the 
    /// protocol paramters into a single byte array 
    /// </summary> 
    private void VectorizeProtParList() 
    { 
     if (listofArrays != null && listofArrays.Count > 0) 
     { 
      var flattenedList = 
       listofArrays.SelectMany(bytes => bytes); 

      savedPPDataArray = flattenedList.ToArray(); 

      MessageBox.Show("New Protocol parameter data saved", "Save Data", 
       MessageBoxButtons.OK, MessageBoxIcon.Information); 
     } 
     else 
     { 
      MessageBox.Show("PP Data list seems to have no data", "Error", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 

    } 

savedPPDataArray是我寫回到文件的最終字節緩衝區。

乾杯, Harish