4

我有一个 C#.Net 应用程序,它从由 Oracle 10 db 支持的商业应用程序访问数据。商业应用程序数据库中的几个字段(声明为 varchar2(n))包含特殊字符。例如,“智能引用”撇号。商业客户端应用程序正确显示这些字符,但我的应用程序将它们显示为倒置问号。Oracle 字符集是“WE8ISO8859P1”。

我的应用程序使用 System.Data.OracleClient.OracleDataAdapter 读取商业数据库,并通过 DataSet.Tables 转换为表。tablerows 被转换为对象,并且相关的字段被存储为字符串。

如果我在从数据库读取数据后立即检查(在调试器中)数据集中的数据,并且特殊字符已经显示不正确。我不知道如何以十六进制字节的形式检查数据以查看真正存在的内容,我也不确定我应该寻找什么。

我还注意到,Toad 也将字符显示为倒置问号。

我们应用程序的一方面将这些记录写入我们自己数据库中的单独表中;发生这种情况时,特殊字符会被修改,并随后显示为框而不是倒置的问号。

如果需要,我可以提供更多信息。感谢您的任何帮助!

4

2 回答 2

2

WE8ISO8859P1 字符集中的某些字符与 UTF8 中的相同字符具有不同的二进制表示。

我建议有两种可能的方法

1) 尝试使用适用于 .NET (ODP.NET) 的 Oracle 本机数据提供程序。Microsoft 的库 System.Data.OracleClient 中可能存在错误/功能,该适配器不自动支持将 WE8ISO8859P1 转换为 unicode。这是 ODP.NET 的链接

我希望在 ODP 中支持这种编码(但说真的我从来没有检查过这个,这只是一个建议)

2)解决方法:在Dataset中,您应该创建一个二进制字段(映射到原始表字段)和一个字符串字段(未映射到数据库)。当您将数据加载到数据集时,迭代每一行并执行从二进制数组到字符串的转换。

代码应该是这样的

Encoding e = Encoding.GetEncoding("iso-8859-1");
foreach(DataRow row in dataset.Tables["MyTable"])
{
    if (!row.IsNull("MyByteArrayField"))
        row["MyStringField"] = e.GetString((row["MyByteArrayField"] as byte[]));
}
于 2009-08-03T14:26:26.607 回答
2

浏览此线程的任何人的后记:

Bogdan 在让我找到“答案”(例如它是)方面非常有帮助,但正如他所指出的那样,您可能没有相同的情况。

  1. 我们与负责使用商业软件的团队进行了沟通。他们一直在从 Word 和 Excel 复制/粘贴,这就是插入特殊字符的方式。

  2. 问题出现在远程数据库和我们的数据库之间的字符翻译中。主机数据库使用字符集 WE8ISO8859P1,我们使用 WE8MSWIN1252。出于公司层面的考虑,目前修改任一字符集都不可行。

  3. 我使用 SYS.UTL_RAW.CAST_TO_RAW(fieldname) 将源字段转换为搜索“BF”(我们字符集中倒置问号的十六进制代码)。这至少让我确定了问题记录和性格。但是,远程记录上的许多不同的特殊字符将/可以转换为 BF。例如,Word 的连字符不是简单的“破折号”字符,还会被翻译成倒置的问号。

  4. dump(fieldname) 在翻译之前以某种方式转换为十进制字符代码,除非我还在同一个查询中使用了 SYS.UTL_RAW.CAST_TO_RAW。这引起了惊人的头痛。dump() 本身可用于从源数据库中识别特定的预翻译字符。

最好的解决方案是在两个数据库上使用相同的字符集。由于这对我们来说是不可能的,我们已经手动将源(远程)数据库上出现的所有特殊字符替换为非特殊等价物(正则撇号或连字符)。但是,由于商业软件没有更正或标记特殊字符,我们将来可能会遇到这个问题。因此,我们的更新应用程序将扫描倒置的问号,并向系统所有者发送带有不良记录 ID 的通知。就像许多其他公司情况一样,这将不得不这样做。;-)

再次感谢博格丹!

于 2009-08-05T15:13:22.877 回答