Греческий текст не отображается правильно - PullRequest
1 голос
/ 04 августа 2009

У нас есть приложение, которое использовало среду C ++ zApp для пользовательского интерфейса (формы, шрифты, все). Мы медленно преобразовали его для использования .net Framework и недавно обнаружили, что греческие символы больше не отображаются правильно.

В одной версии приложения у меня есть форма 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 устанавливается. Греческий все еще отображался неправильно. Я могу сказать, что созданный мной шрифт используется, потому что, если я установлю подчеркивание, он подчеркнет текст, и если я посмотрю на свойства шрифта элемента управления (this.Font) после установки его с помощью LOGFONT, они будут такими же, как я ожидайте, что они будут. Сначала у меня были проблемы со шрифтом, который не был шрифтом истинного типа, но затем переключил шрифт zApp на шрифт истинного типа, и он все еще был в порядке, поэтому я использовал его для своих тестов (Microsoft Sans Serif).

Кроме того, если я наберу греческие символы с клавиатуры, они будут правильно отображаться как в форме .net, так и в форме zApp, однако символы, введенные в форму .net и сохраненные в базе данных, будут отображаться как мусор в zApp. формы и отличаются от данных, сохраненных в форме zApp. Опять же, если я скопирую текст, который выглядит как мусор, из формы .net и вставлю его в форму zApp, он будет отображаться нормально (без потери данных).

У кого-нибудь есть идеи?

Ответы [ 2 ]

2 голосов
/ 04 августа 2009

Я создал небольшое тестовое приложение на C # и сделал кнопку с текстом на греческом языке: ελληνικά. Как только я установил текст в кнопке, Visual Studio спросила меня, хочу ли я перейти на Unicode, я ответил «да». После этого греческий текст показывался на моей кнопке.

Я подозреваю, что в Visual Studio или в каком-либо свойстве конфигурации вашего приложения есть параметр, который необходимо установить правильно.

Edit:

Ваша дальнейшая информация в вашем ответе заставляет меня думать, что текст из базы данных Oracle может быть UTF-8 . Если это так, то некоторые старшие биты используются для определения, есть ли еще байты в данном символе. Таким образом, не все символы имеют одинаковую длину байта! Ваше решение может не сработать. Я предлагаю попробовать загрузить его, используя

Encoding.UTF8.GetString()
1 голос
/ 05 августа 2009

Я понял, как заставить текст правильно отображаться в форме .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));

что экономит мусор. Значение строки «Имя» выглядит нормально. Неуправляемый код C ++, который работает, просто собирает SQL-оператор в массив символов (греческий текст всегда также обрабатывается в массиве char) и выполняет его с помощью вызова функции OCI (API Oracle). Код .net использует ODAC (клиент доступа к данным Oracle) для доступа к базе данных.

ОБНОВЛЕНИЕ:

Я решил вторую часть своей проблемы (сохранение) и узнал больше о том, что происходит.

Данные, поступающие в .net из Oracle, выглядят так в памяти, когда я помещаю их в строковый тип данных .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 00 .. 3y ........ Τ .α.μ.ε.ί.ο ............

Эта строка некорректно отображается в .net как:
Ôáìåßï

Содержимое памяти строки .net после преобразования (код преобразования показан выше):
00 0a 33 79 07 00 00 00 06 00 00 00 a4 03 b1 03 до н.э. 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)));  

Вся эта штука такая хакерская - если у кого-то есть способ получше, поделитесь им. Кажется, должен быть какой-то простой способ решения всей этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...