C# OLEDB自定义编码

C# OLEDB自定义编码,c#,.net,encoding,oledb,C#,.net,Encoding,Oledb,我的目标 我需要以客户机指定的特定格式创建一个.dbf文件。采用kamenicky编码的dBase III.dbf格式,使用整数、不同长度的字符和双列类型 问题 我几乎所有的东西都正常工作了,但只有一个障碍:darn编码拒绝工作,尽管编写了一个特定的转换表,将原始字符与kamenicky编码兼容的字符进行切换。这意味着输出文件的结尾是一个字符的十六进制值FF,该字符在导入的字符串中被指定为十六进制值A0 如果你要回答(-1)这个问题,我将非常感谢你在评论中提供为什么这样做的信息——即使是“你对这

我的目标

我需要以客户机指定的特定格式创建一个.dbf文件。采用kamenicky编码的dBase III.dbf格式,使用整数、不同长度的字符和双列类型

问题

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

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

我已经解决了这个问题(见评论),但这个解决方案是有缺陷的,根本不能回答给定的问题

问题

如何说服Jet.OLEDB提供程序不要弄乱编码

我试过什么

  • 使用foxpro provider,它实际上工作得很好,除了一个小细节,即我的客户机软件无法读取生成的.dbf文件

  • 在不使用OLEDBPParameter的情况下插入数据(因此无法正确转义输入)无效

  • 通过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;
}
private void insertRows(T[]数据,OLEDB连接)
{
使用(OleDbCommand=connection.CreateCommand())
{
对于(int i=0;i
下面是一个我尝试过的快速方法,它似乎是在使用特殊的Unicode字符和您尝试使用的代码页895的正确识别。这确实使用了来自Microsoft的VFP OleDb提供程序。然而,我有四个部分

  • 创建带有显式代码页引用的表,该引用通常会产生VFP可读格式

  • 要保留dBASE中所需的向后兼容性,请使用COPY To命令将VFP version表头转换为旧的(并且应该是)dBASE可识别的格式

  • 简单地插入到表的dBASE版本中(也是代码页895)

  • 检索所有记录并查看Unicode结果


  • 很明显,您有代码来循环遍历所有列并设置适用的参数,因此我将此留给您。

    我已经解决了这个问题,尽管解决方案还远远不够完美。Jet.OLEDB使用的任何编码似乎都是(至少对于重要的字符而言)8位字符集,kamenicky编码也是如此。因此,在OLEDB provider完成文件的编写之后,我再次以字节表示形式打开它,并手动替换字符,以便它们遵循kamenicky编码。当然,这并不是对原始问题的回答——只是我迫不得已不得不求助的解决方案。昨天,我已经将我在评论中提出的原始问题下的解决方案发送给了测试,似乎效果不错。遗憾的是,目前我没有时间正确地实施/测试您的解决方案-如果我将来有时间,我可能会回到这个问题上来,我会让您知道它是否有效。无论如何,虽然未经测试,但我看不出任何理由说明它不应该起作用,所以我会给你赏金/答案(至少在未经测试的情况下)。谢谢你的努力。
    // 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"];
    }