2009-08-04 94 views
1

我们有一个应用程序,它使用用于UI(表单,字体,一切)的C++ zApp框架。我们已经慢慢地将其转换为使用.net框架,并且最近发现希腊字符不再正确显示。希腊文不能正确显示

在应用程序的一个版本中,我有一个C#.net表单和一个C++ zApp表单,它们都显示相同的数据。该项目使用MS Visual Studio 2005编译并使用.net 2.0。在.net格式中希腊文显示不正确。我可以从.net表单复制文本,将其粘贴到zApp表单中,并且它将在zApp表单中正确显示。这告诉我,数据正在加载好,并且所有正确的信息都在字符串中。

我试着对.net代码中使用的字体进行更改。 zApp代码使用显示希腊语的控件的LOGFONT结构创建字体。我使用了zApp使用的确切值,创建了具有这些值的LOGFONT并使用该结构设置了.net窗体的字体(this.Font = Font.FromLogFont((object)lFont);)。我使用了相同的面名,字符集等。LOGFONT结构中的所有内容都已设置好。希腊人仍然显示错误。我可以说,我创建的字体被使用,因为如果我设置下划线,它会强调文本,如果我用LOGFONT设置它后查看控件字体的属性(this.Font),它们就像我想要的那样期待他们。我最初有一个字体不是真正的字体,但随后将zApp字体转换为真正的字体,并且它仍然很好,所以我用它来测试(Microsoft Sans Serif)。另外,如果我从键盘输入希腊字符,它们将以.net格式和zApp格式正确显示,但是,以.net格式输入并保存到数据库的字符将显示为zApp表单并与zApp表单保存的数据不同。同样,如果我将.net表单中看起来像垃圾的文本复制并粘贴到zApp表单中,那么它显示得很好(不会丢失数据)。

有没有人有任何想法?

回答

1

我想出了如何让文本以.net形式正确显示。它实际上与字体无关,而且更多的是为.net转换数据。我已经改变了代码,基本上是这样的:

string Name = reader.GetString(column); 

string Name = System.Text.Encoding.Default.GetString(reader.GetOracleString(column).GetNonUnicodeBytes()); 

我仍然要确认这不会导致问题,任何其他语言的客户端使用的是已经工作的罚款,但到目前为止希腊语和英语看起来不错。

现在我需要在添加用于保存的OracleCommand参数时反转该过程。原来的代码是这样的:

cmd.Parameters.Add(new OracleParameter(":name", Name)); 

它节省垃圾。字符串“Name”的值看起来很好。工作的非托管C++代码只是将一个sql语句放在一个字符数组中(希腊文本总是在一个char数组中处理),并通过调用OCI函数(Oracle的API)来执行它。 .net代码使用ODAC(Oracle数据访问客户端)进行数据库访问。

UPDATE:

我已经解决了我的问题(保存)的第二部分,更多地了解正在发生的事情。

的数据来从甲骨文到.NET看起来像这样在内存中,当我把它变成一个.NET字符串数据类型,而不做任何转换:

00 0A 33 79 07 00 00 00 06 00 00 00 d4 00 e1 00 ec 00 e5 00 df 00 ef 00 00 00 00 00 00 00 00 00 00 00 00 ..3y ........t.α.μ.ε.ί.ο..... .......

此字符串显示不正确在.NET为:
Ôáìåßï

在.NET字符串的存储器内容转换后(转化如上所示代码):
00 0a 33 79 07 00 00 00 06 00 00 00 a4 03 b1 03 bc 03 b5 03 af 03 bf 03 00 00 00 00 00 00 00 00 00 00 00 .3y ........¤。 ±.Ό.μ.-。.... ............

您可以看到,对于每个字符,已从低位字节的高半字节中取出3,并将其置于高位字节。
字符串现在显示正确.NET为:
Ταμείο

如以上示出了信息,似乎.NET不同表示字符比非托管C++和Oracle。我做了一些测试,发现突破点是160(十六进制值a0)。所以当使用0到159(00到9f)的字符值时,没有区别。一旦使用160或更高的值,就会有所不同。

我的解决方案只适用于0到255之间的字符值,因为我在转换中删除了字符的高字节。这应该适用于我们的应用程序,尽管我们从来不支持多字节字符集。

我在做字符串转换回的格式保存到Oracle什么简化版本是:

//"name" represents a .net string data type containing the data to save 

char[] textChars = new char[4000]; //4000 is the max varchar2 column size in Oracle 
byte[] textBytes; 
int index = 0; 
textBytes = (System.Text.Encoding.Default.GetBytes((name).ToCharArray())); 
foreach (byte textByte in textBytes) 
{ 
    textChars[index++] = (char)textByte; 
} 
string textString = new string(textChars, 0, index); 
cmd.Parameters.Add(new OracleParameter(":name", (object)(textString))); 

这整个事情是这样的黑客 - 如果任何人有一个更好的办法,请分享它。似乎应该有一些简单的方法来处理整个问题。

2

我在C#中创建了一个小测试应用程序,并制作了一个带有一些希腊文字的按钮:ελληνικά。只要我在按钮中设置文本,Visual Studio问我是否要切换到Unicode,我说'是'。之后,希腊文显示在我的按钮上。

我怀疑在Visual Studio中有一个设置或者需要正确设置应用程序配置的某些属性。

编辑:

你在你的答案更多的信息让我相信从Oracle数据库中的文本可能是UTF-8。如果是,则使用一些高位来定义给定字符中是否有更多字节。因此,并非所有的字符都是相同的字节长度!你的解决方案可能无法工作我建议试图加载它使用

Encoding.UTF8.GetString() 
+0

我很确定我的项目已经在使用Unicode。这就是为什么如果我从.net窗体获取文本并将其粘贴到zApp窗体中,那很好。这些角色的数据不会丢失。但只是为了测试你的建议,我添加了一个带有按钮的新表单,并没有任何提示切换到Unicode。它以同样的方式显示 - 如果我从我的键盘输入希腊语,它会显示正常,但数据库中的希腊语和zApp格式不显示。 – AAyres 2009-08-04 18:40:01

+0

根据我已阅读的有关WE8ISO8859P1的内容,我在Oracle数据库中使用的字符应始终为单个字节长度。 – AAyres 2009-08-06 16:32:50