我正在努力用C#程序从数据库中读取二进制记录。这些记录是用Borland Delphi创建的。下面是一个例子:
// Delphi record definition
tBowler_Rec = Record
public
gender : tGender;
bowler_num : byte;
name : tString32;
initials : String[3];
...
// Corresponding C# definition (unmanaged code)
[StructLayout(LayoutKind.Sequential, Pack=4)]
public unsafe struct tBowler_Rec
{
public tGender gender;
public byte bowler_num;
public fixed byte name[32];
public fixed byte initials[3];
...
我实际上能够从SQL Server数据库中读取这个二进制结构,并在Visual Studio调试器中查看数据。耶!我能够访问像"gender"和"bowler_num"这样的字段,没有任何问题。耶!
问:如何将"name"转换为C#字符串?
一个示例名称是"ASHTON"。它在内存中如下所示:
\0x6ASHTON\0x0\0x0...
下面是我尝试访问它的方式:
[StructLayout(LayoutKind.Sequential, Pack=4)]
public unsafe struct tBowler_Rec
{
public tGender gender;
public byte bowler_num;
public fixed byte name[32];
...
public string Name
{
get
{
StringBuilder sb = new StringBuilder();
int ilen = name[0];
for (int i = 1; i <= ilen; i++)
sb.Append(name[i]);
return sb.ToString();
}
}
我得到这个错误:
错误:不能使用非固定表达式中包含的固定大小缓冲区。请尝试使用fixed语句。
4条答案
按热度按时间bwntbbo31#
由于我对 Delphi 不是很熟悉,所以我不能直接回答
tString32
字段,它似乎是UnmanagedType.AnsiBStr。如果是这样的话,我会选择这样的东西:
再看看我是如何进行
initials
封送处理的,如果tString不是AnsiBStr,这将是封送name中的字符的更好方法。我还想说明一下,我已经从结构声明中删除了固定的和不安全的指令,因为这对您要做的事情来说是不必要的。
wd2eg0qa2#
试试看
piztneat3#
以原始格式存储的字符串不是“null terminated”(C样式字符串)。
原始格式是'字符计数然后计数字符=〉0x6 =字符计数,A = 0 S = 1 H = 2 T = 3 O = 4 N = 5。
您尝试读取字符,直到遇到空字符。但是没有空字符,它不是空终止字符串。您必须为此设置自定义数据转换器或转换数据库。
mpgws1up4#
我在这里找到了答案:Fixed size buffer cannot be directly used from "this" object
溶液:``
弗拉基米尔绝对是在正确的轨道上:根本问题是我需要将这个Delphi数组作为值类型,而不是C#(引用类型)数组来处理。解决方法是"MarshalAs(UnmanagedType.ByValArray)"/
谢谢大家!