我正在努力使用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”等字段。耶!
问:如何将“名称”变成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语句。
帮助?????
提前谢谢!
答案 0 :(得分:2)
由于我对Delphi不是很熟悉所以我不能在tString32
字段给你一个直接答案。它似乎是UnmanagedType.AnsiBStr。
如果是这种情况,我会选择这样的事情:
[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct tBowler_Rec
{
public tGender gender;
public byte bowler_num;
[MarshalAs(UnmanagedType.AnsiBStr)]
public string name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public char[] initials;
还要看看我是如何进行initials
封送的。如果tString不是AnsiBStr,这将是从名称封送字符的更好方法。
我还想表明我已从结构声明中删除了固定和不安全的指令,因为这对于您尝试执行的操作不是必需的。
答案 1 :(得分:2)
尝试
Encoding.ASCII.GetString(name, 1, name[0]);
答案 2 :(得分:1)
以原始格式存储的字符串不是“空终止”(C样式字符串)。
原始格式为'char count Then Count chars =&GT; 0x6 =字符计数,A = 0 S = 1 H = 2 T = 3 O = 4 N = 5.
您尝试读取Chars,直到遇到null char。但是没有null char,它不是一个以null结尾的字符串。您必须为此设置自定义数据连接器或转换数据库。
答案 3 :(得分:0)
我在这里找到答案: Fixed size buffer cannot be directly used from "this" object
解决方案:
[StructLayout(LayoutKind.Sequential, Pack=4)]
public unsafe struct tBowler_Rec
{
public tGender gender;
public byte bowler_num;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public byte[] name;
...
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();
}
}
Vladimir绝对走在正确的轨道上:根本问题是我需要将这个Delphi数组视为值类型,而不是C#(引用类型)数组。解决方案是“MarshalAs(UnmanagedType.ByValArray)”/
谢谢大家!