我们有一个应用程序使用C ++ zApp框架用于UI(表单,字体,所有内容)。我们已慢慢将其转换为使用.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);)。我使用了相同的facename,charset等.LOGFONT结构中的所有东西都被设置了。希腊语仍然显示错误。我可以说我创建的字体正在被使用,因为如果我设置下划线它会强调文本,如果我在用LOGFONT设置后查看控件字体(this.Font)的属性,它们就像我一样期待他们。我最初遇到的问题是字体不是真正的字体,但后来将zApp字体切换为真正的字体,它仍然很好,所以我用它进行测试(Microsoft Sans Serif)。
此外,如果我从键盘输入希腊字符,它们在.net表单和zApp表单中都能正确显示,但是,在.net表单中输入并保存到数据库的字符将在zApp中显示为垃圾表单,与zApp表单保存的数据不同。同样,如果我从.net表单中复制看起来像垃圾的文本并将其粘贴到zApp表单中,那么它就会显示正常(不会丢失数据)。
有没有人有任何想法?
答案 0 :(得分:2)
我在C#中创建了一个小测试应用程序,并制作了一个带有一些希腊文字的按钮:ελληνικά。一旦我在按钮中设置了文本,Visual Studio就会问我是否要切换到Unicode,我说'是'。之后,希腊文字显示在我的按钮上。
我怀疑Visual Studio中的设置或应用程序配置的某些属性需要正确设置。
修改强>
您在回答中的更多信息让我相信Oracle数据库中的文本可能是UTF-8。如果是,则使用一些高位来定义给定字符中是否有更多字节。因此,并非所有字符都是相同的字节长度!您的解决方案可能无效。我建议尝试使用
加载它Encoding.UTF8.GetString()
答案 1 :(得分: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数据访问客户端)进行数据库访问。
更新:
我已经解决了问题的第二部分(保存)并且更多地了解了正在发生的事情。
当我将其放入.net字符串数据类型而不进行任何转换时,来自Oracle的.net数据在内存中看起来像这样:
<00> 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 .3y ........Τ .α.μ.ε.ί.ο............此字符串在.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 .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)));
整个事情就是这样一个黑客 - 如果有人有更好的方法,请分享。似乎应该有一些简单的方法来处理整个问题。