我有一个C#.Net应用程序,可以访问Oracle 10 db支持的商业应用程序中的数据。商业应用程序数据库中的几个字段(声明为varchar2(n))包含特殊字符。例如,“智能报价”撇号。商业客户端应用程序正确显示这些字符,但我的应用程序将它们显示为反向问号。 Oracle字符集是“WE8ISO8859P1”。
我的应用程序使用System.Data.OracleClient.OracleDataAdapter读取商业数据库,通过DataSet.Tables转换为表。将表格转换为对象,并将相关字段存储为字符串。
如果我在从数据库中读取数据后立即检查(在调试器中)数据,并且特殊字符已经错误显示。我无法弄清楚如何将数据作为十六进制字节来检查,看看它到底有什么,我也不确定我应该寻找什么。
我还注意到Toad也将字符显示为倒置问号。
我们的应用程序的一个方面是将这些记录写入我们自己的数据库中的单独表中;当发生这种情况时,特殊字符会被修改,然后显示为方框而不是倒置的问号。
如果需要,我可以提供更多信息。感谢您的帮助!
答案 0 :(得分:2)
WE8ISO8859P1字符集中的某些字符与UTF8中的相同字符具有不同的二进制表示形式。
我建议的是两种可能的方式
1)尝试使用适用于.NET的Oracle本机数据提供程序(ODP.NET)。可能是Microsoft的库System.Data.OracleClient中存在一个错误/功能,该适配器不会自动支持将WE8ISO8859P1转换为unicode。 Here is a link to ODP.NET
我希望在ODP中支持这种编码(但是说实话我从未检查过这个,这只是一个建议)
2)解决方法:在Dataset中,您应该创建一个二进制字段(映射到原始表字段)和一个String字段(未映射到数据库)。将数据加载到数据集时,迭代每一行并从二进制数组转换为字符串。
代码应该是这样的
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[]));
}
答案 1 :(得分:2)
浏览此帖子的人的后记:
Bogdan非常乐于帮助我找到“答案”(例如它),但正如他所指出的那样,你可能没有相同的情况。
我们与负责使用商业软件的团队进行了沟通。他们一直在从Word和Excel中复制/粘贴,这就是特殊字符的插入方式。
远程数据库和数据库之间的字符转换出现问题。主机数据库使用字符集WE8ISO8859P1,我们的使用WE8MSWIN1252。由于公司层面的顾虑,现在修改任何一个字符集都是不可行的。
我使用SYS.UTL_RAW.CAST_TO_RAW(fieldname)转换源字段以搜索'BF'(我们的字符集中的反转问号的十六进制代码)。这至少让我找出问题记录和字符。但是,远程记录中的许多不同的特殊字符将/可以转换为BF。例如,Word的连字符不是简单的“破折号”字符,也会转换为反转的问号。
dump(fieldname)在翻译之前以某种方式转换为十进制字符代码,除非我在同一查询中使用了SYS.UTL_RAW.CAST_TO_RAW。这引起了惊人的头痛。 dump()本身可用于从源db中识别特定的预翻译字符。
最佳解决方案是在两个dbs上使用相同的字符集。由于这对我们来说是不可能的,因此我们使用非特殊等效项(常规撇号或连字符)手动替换源(远程)数据库上所有出现的特殊字符。但是,由于商业软件没有更正或标记特殊字符,我们将来可能会遇到这个问题。因此,我们的更新应用程序将扫描反转的问号,并使用坏记录的ID向系统所有者发送通知。像许多其他公司情况一样,这将是必须的。 ; - )
再次感谢,波格丹!