在不同的计算机上编码dBase III .dbf文件的问题

时间:2010-10-02 12:46:15

标签: c# .net encoding odbc dbf

我正在使用C#和.NET 3.5,尝试使用带有Microsoft dBase驱动程序的ODBC从旧的dbf文件导入一些数据。

dbf采用dBase III格式,并使用ibm850编码进行字符串处理。

现在,当我在我的机器上运行我的程序时,从OdbcDataReader读取的所有字符串数据都会转换为UTF-16或UTF-8或者其他东西,idk并且我将它保存为UTF-8并且一切正常,但是我尝试在XP机器上使用这个程序,有些字符没有正确转换为UTF-8。 'Õ'例如。也可能还有其他一些。 'Ä','Ö'和'Ü'等字符都可以。这就是问题。 也许ODBC或驱动程序使用一些机器文化信息或其他东西搞乱一切。

是否可以从数据库中读取字符串作为二进制文件?也许某些功能如CONVERT或CAST?或者我在哪里可以找到适用于此dBase驱动程序或其他驱动程序的SQL函数和语法的一些参考?我四处搜寻,找不到任何东西。使用ODBC和SQL时我感到很盲目。

现在我正在使用临时黑客用Õ替换所有σ。

谢谢!

示例代码:

System.Data.Odbc.OdbcConnection oConn = new System.Data.Odbc.OdbcConnection();
oConn.ConnectionString = @"Driver={Microsoft dBase Driver (*.dbf)};DriverID=277;Dbq=" + dbPath + ";";
oConn.Open();

System.Data.Odbc.OdbcCommand oCmd = oConn.CreateCommand();
oCmd.CommandText = @"SELECT name FROM " + dbPath + "TABLE.DBF";

System.Data.Odbc.OdbcDataReader reader = oCmd.ExecuteReader();
reader.Read();

byte[] buf = Encoding.UTF8.GetBytes(reader.GetString(0));
BinaryWriter writer = new BinaryWriter(File.Open(@"C:\DBF\Test.txt", FileMode.Create));
writer.Write(buf);

结果:

dbf中的E5(850中的Õ)

pc1上的Test.txt:C3 95(UTF-8中的Õ)

pc2上的Test.txt:CF 83(UTF-8中的σ)

4 个答案:

答案 0 :(得分:2)

如果您仍然遇到这些文件的问题,我可以帮助您。

文件中偏移29(十进制)的“代码页字节”又称“语言驱动程序ID”(LDID)是什么?

我有一个基于Python的DBF阅读器,它可以读取任何字段数据类型和任何代码页 - 它有一个很长的列表,从代码页字节到代码页编号的各种映射源编译。选项是(1)相信LDID,传递Unicode(2)忽略LDID,传递未解码的字节(3)覆盖LDID,用特定代码页解码成Unicode。当然可以将Unicode编码为UTF-8。

DBF阅读器还进行了大量合理的交叉检查,这可能有助于调查VFP认为文件损坏的原因。

你怎么知道它正在使用IBM850?我拥有的另一段Python代码是原型编码检测器,与源自Mozilla代码的'chardet'等检测器不同,它不是以网络为中心的,可以很高兴地识别大多数旧的DOS代码页 - 这可能有所帮助。

观察:希腊字母小写sigma(σ)在代码页437中是0xE5,代码页850成功 - “pc2”似乎有点过时......

如果您认为我可以提供任何帮助,请随时发送电子邮件至insert_punctuation(“sjmachin”,“lexicon”,“net”)

答案 1 :(得分:2)

试试这段代码。

var oConn = new System.Data.Odbc.OdbcConnection();
oConn.ConnectionString = "Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + dbPath;
oConn.Open();
var oCmd = oConn.CreateCommand();
oCmd.CommandText = @"SELECT name FROM " + dbPath + "TABLE.DBF";
var reader = oCmd.ExecuteReader();
reader.Read(); 
byte[] A = Encoding.GetEncoding(Encoding.Default.CodePage).GetBytes(reader.GetString(0));
string p = Encoding.Unicode.GetString((Encoding.Convert(Encoding.GetEncoding(850), Encoding.Unicode, A)));

答案 2 :(得分:1)

当你阅读dbf文件时,你应该明白你应该考虑3种类型的编码:

1.编码数据库提供程序读取文件的位置。这取决于     提供者和当前的操作系统。该编码应用于字节数组接收。例如在我的电脑上:

  • 当我使用连接字符串“Data Source = {0}; Provider = Microsoft.JET.OLEDB.4.0;扩展属性= DBase IV;用户 ID =; Password =;“,使用866代码页读取字符串(俄语 MS-DOS)

  • 当我使用连接字符串“Data Source = {0}; Provider = vfpoledb.1; Exclusive = No; Collat​​ing Sequence = Machine“,strings 使用 Encoding.Default (1251代码页)

  • 阅读

2.编写将字符串写入dbf文件的编码。它可以从29字节的dbf文件接收,但实际上无论如何标记dbf文件编码,您应该只知道使用了什么编码。此编码应在字符串转换期间用作源编码

3.编码要转换的字符串。这通常是UTF-8。

因此字符串转换应如下所示:

byte[] bytes = Encoding.GetEncoding(codePage1).GetBytes(reader.GetString(0));

string result = Encoding.UTF8.GetString((Encoding.Convert(Encoding.GetEncoding(codePage2), Encoding.UTF8, bytes)));

答案 3 :(得分:0)

您是否尝试过使用Visual Foxpro驱动程序“VFPOleDb”驱动程序???