我有几个由第三方生成的DBF文件,我需要能够查询。我遇到了麻烦,因为所有列类型都已定义为字符,但其中某些字段中的数据实际上包含二进制数据。如果我尝试使用OleDbDataReader读取这些字段作为字符串或字符数组以外的任何字段,我会抛出InvalidCastException,但我需要能够将它们作为二进制值读取或至少在读取后转换/转换它们。实际上包含文本的列将按预期返回。
例如,第一列定义为长度为2个字节的字符字段,但该字段包含16位整数。
我编写了以下测试代码来读取第一列并将其转换为适当的数据类型,但该值不正确。
数据库的第一行在第一列中的值为17365(0x43D5)。运行以下代码,我最终获得的是17215(0x433F)。我很确定它与使用ASCII编码从数据读取器返回的字符串中获取字节有关,但我不确定将值转换为我需要的格式的另一种方法,其他方法是编写我自己的DBF阅读器并完全绕过ADO.NET,除非我绝对必须这样做,否则我不想这样做。任何帮助将不胜感激。
byte[] c0;
int i0;
string con = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\ASTM;Extended Properties=dBASE III;User ID=Admin;Password=;";
using (OleDbConnection c = new OleDbConnection(con))
{
c.Open();
OleDbCommand cmd = c.CreateCommand();
cmd.CommandText = "SELECT * FROM astm2007";
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
c0 = Encoding.ASCII.GetBytes(dr.GetValue(0).ToString());
i0 = BitConverter.ToInt16(c0, 0);
}
dr.Dispose();
}
答案 0 :(得分:0)
你可能遇到的实际上是一个基于备忘录的字段...这些列实际上在另一个文件中有原始文本(通常是.DBT(dBASE)或.FPT(FoxPro)。它是指针偏移量在文本内容文件中,它是自由格式长度并以块写入,但指针存储在4个字节中。
如果您可以访问.dbf查看器并且可以在某种程度上看到它,那可能对您有所帮助。
答案 1 :(得分:0)
我很确定你对ASCII字符转换是正确的。我看了一下Jet引擎支持的标量函数,但无法找到它们......或者说我发现列出的标量函数但没有语法。 CONVERT
函数可能就是你想要的。类似的东西:
SELECT CONVERT(twobytefield, SQL_BINARY) from astm2007
然后你可以调用dr.GetBytes()
来读取原始数据。但是,我无法使用Jet引擎喜欢的函数构造语句。
如果您无法使转换工作,另一种可能性是使用Advantage .NET Data Provider。或者OLE DB提供程序(但是因为您使用C#,.NET数据提供程序可能更适合)。该提供程序读取DBF文件并支持CONVERT标量函数。它有一个免费的本地引擎。
既然你提到你要尝试它,因为我测试它以确保我没有说谎,这是我使用的代码片段:
AdsConnection conn = new AdsConnection(
@"data source=c:\path;chartype=ansi;ServerType=local;TableType=cdx;" );
conn.Open();
AdsCommand cmd = conn.CreateCommand();
cmd.CommandText = "select cast(somefield as sql_binary) from sometable";
cmd.CommandType = CommandType.Text;
AdsExtendedReader rdr = cmd.ExecuteExtendedReader();
rdr.Read();
byte[] c0 = rdr.GetBytes( 0 );
int i0 = BitConverter.ToInt16( c0, 0 );
Console.WriteLine( "val = {0}", i0 );