2009-08-04 9 views
1

Nous avons une application qui utilisait le framework C++ zApp pour l'interface utilisateur (formulaires, polices, tout). Nous l'avons lentement converti pour utiliser le framework .net et avons récemment découvert que les caractères grecs ne s'affichent plus correctement.Le texte grec n'est pas affiché correctement

Dans une version de l'application, j'ai un formulaire C# .net et un formulaire zapp C++ qui affichent tous deux les mêmes données. Le projet est compilé avec MS Visual Studio 2005 et utilise .net 2.0. Dans le formulaire .net, le grec n'est pas affiché correctement. Je peux copier le texte à partir du formulaire .NET, le coller dans le formulaire zApp et il s'affichera correctement dans le formulaire zApp. Cela me dit que les données sont en cours de chargement et toutes les informations correctes sont présentes dans la chaîne.

J'ai essayé d'apporter des modifications à la police utilisée dans le code .net. Le code zApp crée une police à l'aide d'une structure LOGFONT pour le contrôle affichant le grec. J'ai pris les valeurs exactes qui étaient utilisées pour zApp, j'ai créé un LOGFONT avec ces valeurs et j'ai défini la police du formulaire .net en utilisant cette structure (this.Font = Font.FromLogFont ((object) lFont);). J'ai utilisé le même nom de facette, le jeu de caractères, etc. Tout dans la structure LOGFONT est mis en place. Le grec était encore mal montré. Je peux dire que la police que j'ai créée est utilisée parce que si je souligne, elle soulignera le texte et si je regarde les propriétés de la police du contrôle (this.Font) après l'avoir définie avec LOGFONT, elles sont comme je le ferais Attends-les à être. J'ai d'abord eu des problèmes avec une police qui n'était pas une police de type vrai, mais j'ai ensuite changé la police zApp en une police de type vrai et c'était toujours bien, donc j'ai utilisé ça pour mes tests (Microsoft Sans Serif). De plus, si je tape des caractères grecs à partir du clavier, ils s'affichent correctement dans le formulaire .net et le formulaire zApp. Cependant, les caractères entrés dans le formulaire .net et enregistrés dans la base de données s'afficheront comme des ordures dans le fichier. Les formulaires zApp sont différents des données enregistrées par le formulaire zApp. Encore une fois, si je copie le texte qui ressemble à la poubelle du formulaire. NET et le collez dans le formulaire zApp alors il affiche très bien (pas de perte de données).

Quelqu'un a-t-il des idées?

Répondre

1

J'ai trouvé comment obtenir le texte à afficher correctement dans le formulaire. Il n'a en fait rien à voir avec la police et plus à voir avec la conversion des données pour .net. J'ai changé le code qui était essentiellement comme suit:

string Name = reader.GetString(column); 

à

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

Je dois encore vérifier que cela ne pose pas de problème pour toute l'utilisation d'autres langues des clients qui ont travaillé bien , mais jusqu'à présent, il semble bien avec le grec et l'anglais.

Maintenant, j'ai besoin d'inverser ce processus lors de l'ajout du paramètre OracleCommand pour l'enregistrement. Le code original était quelque chose comme ceci:

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

qui économise les ordures. La valeur de la chaîne "Name" semble correcte. Le code C++ non géré qui fonctionne ne fait qu'assembler une instruction sql dans un tableau de caractères (le texte grec est toujours géré dans un tableau char) et l'exécute avec un appel à une fonction OCI (API d'Oracle). Le code .net utilise ODAC (Oracle Data Access Client) pour l'accès à la base de données.

MISE À JOUR:

J'ai résolu la deuxième partie de mon problème (économie) et a appris plus sur ce qui se passe.

Les données provenant pour .NET à partir d'Oracle ressemble à ceci en mémoire quand je l'ai mis dans un type de données chaîne .net sans faire de conversion:

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 ........ Τ.α.μ.ε.ί.ο ..... .......

Cette chaîne affiche de façon incorrecte dans .net que:
Ôáìåßï

le contenu de mémoire de la chaîne de .net après la conversion (conversion de code indiqué ci-dessus):
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 ........ ¤. ± .Ό. Μ .-.. ............

Vous pouvez voir que pour chaque caractère, 3 a été pris du grignotage haut de l'octet faible et mis dans le haut octet.
La chaîne affiche désormais correctement dans .net comme:
Ταμείο

Comme les informations ci-dessus montre, il semble que .net représente des personnages différemment que C++ non géré et Oracle. J'ai fait quelques tests et j'ai trouvé que le point de rupture est 160 (valeur hexadécimale a0). Donc, lorsque vous utilisez des valeurs de caractères de 0 à 159 (00 à 9f), il n'y a pas de différence. Dès qu'une valeur de 160 ou plus est utilisée, il y aura une différence.

Ma solution ne fonctionne que pour les valeurs de caractères comprises entre 0 et 255 car je supprime l'octet de poids fort du caractère dans mes conversions. Cela devrait fonctionner pour notre application, car nous n'avons jamais supporté les jeux de caractères multi-octets de toute façon.

La version simplifiée de ce que je fais pour convertir la chaîne en un format pour l'enregistrement d'Oracle est la suivante: - si quelqu'un a une meilleure façon, s'il vous plaît

//"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))); 

Ce que tout cela est un bidouille Partagez-le. Il semble qu'il devrait y avoir une façon simple de gérer tout ce problème.

+0

Etes-vous sûr que le texte Oracle n'est pas UTF-8? Je sais que les bits de poids fort sont utilisés pour définir s'il y a plus d'octets dans le caractère donné. Donc, en UTF-8, tous les caractères n'ont pas la même longueur - votre solution casserait pour les caractères latins normaux. –

+0

Le texte est stocké dans un VARCHAR2 afin qu'il utilise le jeu de caractères WE8ISO8859P1. (AL16UTF16 est le paramètre NLS_NCHAR_CHARACTERSET.) – AAyres

2

J'ai créé une petite application de test en C#, et fait un bouton avec du texte grec: ελληνικά. Dès que j'ai défini le texte dans le bouton, Visual Studio m'a demandé si je voulais passer à Unicode, j'ai répondu 'oui'. Après cela, le texte grec a montré sur mon bouton.

Je suppose qu'il existe un paramètre dans Visual Studio ou une propriété de votre configuration d'application qui doit être définie correctement.

Edit:

Votre plus d'informations dans votre réponse me porte à croire le texte de la base de données Oracle pourrait être UTF-8. Si c'est le cas, alors certains des bits de poids fort sont utilisés pour définir s'il y a plus d'octets dans le caractère donné. Ainsi, tous les caractères n'ont pas la même longueur d'octets! Votre solution pourrait ne pas fonctionner. Je suggère d'essayer de le charger en utilisant

Encoding.UTF8.GetString() 
+0

Je suis à peu près certain que mon projet utilise déjà Unicode. C'est pourquoi si je prends le texte du formulaire. NET et le collez dans le formulaire zApp c'est très bien. Il n'y a pas de perte de données des personnages. Mais juste pour tester votre suggestion, j'ai ajouté un nouveau formulaire avec un bouton pour le projet et n'a reçu aucune invite pour passer à Unicode. Il s'affiche de la même manière - si je tape grec à partir de mon clavier, il s'affiche bien, mais pas le grec de la base de données et le formulaire zApp. – AAyres

+0

Les caractères avec lesquels je travaille dans la base de données Oracle doivent toujours être d'une longueur d'un octet, d'après ce que j'ai lu à propos de WE8ISO8859P1. – AAyres

+0

Il semble qu'il doit être converti en UTF-16 pour être affiché dans .net. Donc, nos données Oracale sont à un seul octet, ma solution ci-dessus convertit en UTF-16 pour afficher correctement dans .net, puis les convertit en données de caractères mono-octet pour le stockage dans Oracle et affiche en C++ non managé. Cela vous semble-t-il correct? – AAyres

Questions connexes