2009-08-04 102 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