OLEDB自定义编码

本文关键字:编码 自定义 OLEDB | 更新日期: 2023-09-27 18:24:41

我的目标

我需要创建一个由客户端指定的特定格式的.dbf文件。格式为dBaseIII.dbf,采用kamenicky编码,使用Integer、各种长度的Character和Double列类型。

问题

我几乎所有的东西都能工作,只有一个障碍:该死的编码拒绝工作,尽管正在编写一个特定的转换表,将原始字符与与kamenicky编码兼容的字符进行切换。这意味着输出文件以FF的十六进制值结束,例如,在导入的字符串中指定为A0的十六进制的字符。

如果你要(-1)这个问题,我将非常感谢你在评论中提供你为什么这么做的信息——即使是"你对这个问题理解不够"也会有很大帮助,因为我知道在哪里继续我的研究(在这种情况下,最基本的)

我已经在某种程度上解决了这个问题(见评论),但这个解决方案是有缺陷的,根本没有回答给定的问题。

问题

我如何说服Jet.OLEDB提供商不要乱编码?

我试过什么

  • 使用foxpro提供程序,它实际上运行得很好,除了我的客户端软件无法读取生成的.dbf文件这一小细节。

  • 在不使用OleDbParameter的情况下插入数据(这样输入就不会正确转义)对无效

  • 通过CharacterSet=xxx和其他一些我现在不太记得的连接字符串修改设置了几个不同的编码,每次A0的输出都会导致FF。

  • 我在这里找到了一个AutoTranslate属性,但据我所知,它只适用于SQL连接,因为Jet.OLEDB一直给我一个ISAM错误。

  • 我试着在全球化的环境中游刃有余,但没有起到多大作用。

某些代码

连接字符串:

"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0};Extended Properties='"dBase III;'"";

然后使用OleDbCommand插入数据,并用OleDbParameter类和构造的插入字符串填充各个单元格。可能很没用,但下面是代码:

private void insertRows(T[] data, OleDbConnection connection)
{
    using (OleDbCommand command = connection.CreateCommand())
    {
        for (int i = 0; i < data.Count(); i++)
        {
            constructParams(data[i], i, command);
            command.CommandText = constructInsert(i, _fileName);
            command.ExecuteNonQuery();
        }
    }
}
private void constructParams(T data, int index, OleDbCommand command)
{
    command.Parameters.Clear();
    foreach (PropertyInfo prop in _props)
    {
        if(_cols.ContainsKey(prop.Name))
        {
            command.Parameters.Add(new OleDbParameter("@" + prop.Name + index, prop.GetValue(data)));
        }
    }
}
private string constructInsert(int dataNum, string tableName)
{
    string insert = "INSERT INTO [" + tableName + "] (";
    foreach(string key in _cols.Keys)
    {
        insert += "[" + key + "],";
    }
    insert = insert.Remove(insert.Length - 1);
    insert += ") VALUES";
    insert += " (";
    foreach (string key in _cols.Keys)
    {
        insert += "@" + key + dataNum + ",";
    }
    insert = insert.Remove(insert.Length - 1);
    insert += ");";
    return insert;
}

OLEDB自定义编码

这是我尝试过的一个快速的东西,它似乎正在处理特殊的Unicode字符,并在您尝试处理时正确识别代码页895。这确实使用了来自Microsoft的VFP OleDb提供程序。然而,我有四个部分。

  1. 创建具有显式代码页引用的表,这通常会导致VFP可读格式。

  2. 为了保持dBASE中所需的向后兼容性,请使用COPY To命令将VFP版本表标题转换为旧的(应该是)dBASE识别格式

  3. 简单插入dBASE版本的表格(也是代码页895)

  4. 检索所有记录并查看Unicode结果。

// Connection to your data path, but explicitly referencing codepage 895 in connection string
string connectionString = @"Provider=VFPOLEDB.1;Data Source=c:''YourDataPath''SomeSubFolder;CODEPAGE=895;";
string ans = "";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
   // create table syntax for a free table (not part of a database) that is codepage 895.
   string cmd = "create table MyTest1 free codepage=895 ( oneColumn c(10) )";
   OleDbCommand command = new OleDbCommand(cmd, connection);
   connection.Open();
   command.ExecuteNonQuery();
   // Now, create a script to use the MyTest1 table and create MyTest2 which 
   // SHOULD BE recognized in dBASE format.
   string vfpScript = @"use MyTest1
            Copy to MyTest2 type foxplus";

   command.CommandType = CommandType.StoredProcedure;
   command.CommandText = "ExecScript";
   command.Parameters.Add("myScript", OleDbType.Char).Value = vfpScript;
   command.ExecuteNonQuery();
   // Simple insert into the 2nd instance of the table    
   command = new OleDbCommand("insert into Mytest2 ( oneColumn ) values ( ? )", connection);
   command.Parameters.AddWithValue("parmForColumn", "çšjír_Þ‰");
   command.ExecuteNonQuery();
   // Now, get the data back.
   command = new OleDbCommand("select * from Mytest2", connection);
   OleDbDataAdapter da = new OleDbDataAdapter(command);
   DataTable oTbl = new DataTable();
   da.Fill(oTbl);
   if (oTbl.Rows.Count != 0)
      // we should have one row, so get the string from the column
      // and it SHOULD loo like the Unicode sample I inserted above.
      ans = (string)oTbl.Rows[0]["oneColumn"];
}

很明显,您有代码可以循环浏览所有列并设置适用的参数,所以我将这一点留给您。