我坚持这个。
我正在阅读一个二进制文件,其格式如下:
Field name Size in bytes Example
-------------------------------------
Date 19 1998_12_22 PM 20:15
Serial 4 0001
使用以下结构并使用this question的答案我正在尝试阅读该文件。
[StructLayout(LayoutKind.Explicit, Size=23, Pack = 1)]
struct MeasurementStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)]
[FieldOffset(0)]
public string Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
[FieldOffset(19)]
public string Serial;
}
然而,当实例化保存此结构的类时,我在FieldOffset 19处收到错误。不幸的是,此错误是荷兰语,但它大致转换为“无法加载MeasurementStruct,因为19号关闭的字段未对齐(字段可能重叠) )”。
我发现将FieldOffset [19]更改为FieldOffset [20]会使错误消失。但是,在我的情况下,20不是正确的偏移,是吗?
答案 0 :(得分:1)
您的数据(23个字节)和结构大小(24个字节)之间似乎存在大小问题。这是正常的吗?
更新:Pack = 1属性应保证内存对齐,但谷歌搜索会对结构的字段对齐产生不同的响应 。 你可以做的是读取一个字节数组中的23个字节,然后使用Encoding类提取两个字符串:
byte[] array = ... // read 23 bytes
String s1 = Encoding.ASCII.GetString(array, 0, 19);
String s2 = Encoding.ASCII.GetString(array, 19, 4);
答案 1 :(得分:1)
没有一个答案正是我正在寻找的,但我通过定义结构来找到一个更好的方法。
[StructLayout(LayoutKind.Sequential, Size = MeasurementStructSize, Pack = 1)]
struct MeasurementStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)]
public string Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string SerialNumber;
}
我将LayoutKind更改为Sequential。在这种情况下,Pack字段实际上有意义,我不需要添加FieldOffsets。以上工作正常。
非常感谢大家!
答案 2 :(得分:0)
20可能是此架构的正确偏移量。编译器将使用零填充以将struct成员放在偶数位置。确切的“多么均匀”是架构和编译器的依赖,但如果我没有弄错的话,它必须是32位架构中4的倍数。
例如,以下结构:
struct MyStruct
{
char ch; // Offset 0
// 3 "invisible" bytes padding inserted by the compiler
int i; // Offset 4
}
答案 3 :(得分:0)
可能是string
每个字符需要2个字节(unicode),读取为字节数组并使用ASCIIEncoding转换为字符串