【问题标题】:Encoding problems with dBase III .dbf files on different machinesdBase III .dbf 文件在不同机器上的编码问题
【发布时间】:2011-04-20 05:36:24
【问题描述】:

我正在使用 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 中的σ)

【问题讨论】:

    标签: c# .net encoding odbc dbf


    【解决方案1】:

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

    【讨论】:

    • 是的,我有。 Foxpro 驱动程序不喜欢我的数据库 - 告诉我它已损坏,但当我在十六进制编辑器中打开文件并将其与文件格式规范进行比较时,一切看起来都很好。
    【解决方案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") 给我发送电子邮件

    【讨论】:

    • 您好,我在读取 Dbase 文件时也遇到了问题,在我的瑞典 Windows 客户端上读取时工作正常,但在英文操作系统上运行时会弄乱字符,您还在提供帮助吗?
    • @Andreas:给我发电子邮件。文件的 LDID 是什么?你用什么读它? “弄乱字符”没有帮助。显示 repr(预期字符)、repr(实际字符)。如果可能,请将您的代码和文件发给我。
    • 我在 lexicon dot net 给你发了一封电子邮件 sjmachin
    【解决方案3】:

    试试这个代码。

    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)));
    

    【讨论】:

      【解决方案4】:

      当您阅读 dbf 文件时,您应该了解您应该考虑 3 种编码类型:

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

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

      • 当我使用连接字符串“Data Source={0}; Provider=vfpoledb.1;Exclusive=No;整理顺序=Machine”,字符串 使用 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)));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-10
        • 1970-01-01
        • 2012-03-16
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多