动态结构到字节数组转换

时间:2012-12-26 06:51:13

标签: c# arrays buffer

我正在开发一个C#应用程序,它读取二进制文件的内容并在数据网格视图中显示它。数据的格式是这样的

[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;
}

现在,用户可以从datagrid视图更改数据,并将更新的数据保存在缓冲区中,以便可以再次将其写回文件。

我面临的问题是因为数据类型不同。当我想将内容写回字节数组时,由于我遇到的数据类型大小不同,我不能使用固定的结构大小。

有人能告诉我如何创建动态缓冲区并在字节缓冲区中只写入所需的数据大小?

3 个答案:

答案 0 :(得分:2)

您可以使用Marshal类将 Explicit Sequential 布局的结构转换为字节数组。

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);
}

答案 1 :(得分:0)

您需要分配新的缓冲区。必须按原样复制修改后的结构之前的所有数据。必须移位修改后的缓冲区后的所有数据。您可以使用System.Buffer类。

答案 2 :(得分: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是我写回文件的最终字节缓冲区。

干杯, 哈里什