Russian Qt Forum

Qt => Интернационализация, локализация => Тема начата: sibmail от Апрель 20, 2010, 13:42



Название: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 20, 2010, 13:42
Пример кода
...
QTextCodec *codec=QTextCodec::codecForName("CP1251");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForLocale(codec);
...
...

QTextCodec *codec_send = QTextCodec::codecForName("IBM-866");

QString mes_send="ШИШ;
emit message (mes_send); //выводит "ШИШ"

mes_send=codec_send->fromUnicode(mes_send);

emit message (mes_send); //что то там выводит...

mes_send=codec_send->toUnicode(mes_send);

emit message (mes_send); //выводит "?И?"

подскажите что делать?


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 20, 2010, 14:47
Код:
mes_send=codec_send->fromUnicode(mes_send);
Вы преобразуете строку в байтовый массив содержаций вашу строку в кодировке codec_send и затем оператором = преобразуете этот массив к строке посредством кодека установленного в  QTextCodec::setCodecForCStrings(). Соответственно получаете глупость. Смотрите внимательно неявные преобразования между QByteArray и QString в конструкторах копирования и операторах присваивания. Там везде используется кодек QTextCodec::codecForCStrings().


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 04:24
так как конкретно преобразовать?
все буквы нормально работают кроме Ш


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 21, 2010, 09:15
Не совсем понятно чего вы хотите добиться... По любому QString будет хранить строки в юникоде, какую бы кодировку на вход вы не дали. Главное правильный кодек для преобразования всучить, чтобы не получить внутри глупость. Если же вы хотите к примеру из кодировки cp1251 получить ibm-866 (а это однобайтовые кодировки), то можно с помощью кодека 1251 загонять символьный массив (тот же "ШИШ") в QString, а потом с помощью кодека 866 получать массив в QByteArray, и с помощью метода data() уже получать символьный массив в искомой кодировке.

Примерно так:

Код:
char* str1 = "ШИШ"; // исходник должен быть набран в cp1251
QString buf = QTextCodec::codecForName("CP1251")->toUnicode(str1);
char *str2 = new char[buf.size()];
strcpy(str2, QTextCodec::codecForName("IBM-866")->fromUnicode(buf).data());// теперь в str2 содержится ШИШ в кодировке IBM-866


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 11:41
Qt3.3.8
to vadim303 - Не получается...
Детально: в программе формируются строки для посылки, строка состоит из ранзых блоков (в зависимости от протокола).
Я не могу перекодировать все данные перед отправкой, т.к. в служебной части строки есть данные которые нельзя менять.
...
QTextCodec *codec=QTextCodec::codecForName("CP1251");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForLocale(codec);
...
...
QString mes_send1="12345;
QString mes_send2="ШИШ2;
QString mes_send3="ШИШ3;

QTextCodec *codec_send = QTextCodec::codecForName("IBM-866");

mes_send2=codec_send->fromUnicode(mes_send2);
mes_send3=codec_send->fromUnicode(mes_send3);

QString array_Strings[n_devices][1];

array_Strings[0][0]=mes_send2;
array_Strings[1][0]=mes_send3;

QString MES_SEND=mes_send1+array_Strings[0][0]+array_Strings[1][0];  //часть строки должна быть в IBM-866

m_psocket->writeBlock(MES_SEND, MES_SEND.length());


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 21, 2010, 12:18
Блин, опять за старое:
Код:
mes_send2=codec_send->fromUnicode(mes_send2);
codec_send возвращает QByteArray. Я так понимаю ваш ШИШ записанный в исходнике в кодировке 1251 вы преобразуете в 866-ю. Но дальше то опять присваиваете этот QByteArray к QString, а оператор присваивания вызывает преобразование кодеком заданным в QTextCodec::setCodecForCStrings, (кодеком преобразования в 1251). Т.е. вы строку с кодировке 866 преобразуете зачем-то в юникод кодеком для кодеровки 1251 и при этом хотите чтобы получилось что-то осмысленное?


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 12:21
я понимаю это, так что делать то теперь?

ситуация такая что надо иметь строку состоящую из разных кодировок, причем в БД надо записать в 1251, а отправить в 866


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 21, 2010, 12:29
Если вот здесь:
Код:
m_psocket->writeBlock(MES_SEND, MES_SEND.length());
вам надо передать что-то в кодировке 866, то туда не юникод надо передавать (MES_SEND это QString, а QString всегда содержит юникод), а символьный массив (char*) или QByteArray содержащий результат codec_send->fromUnicode(ваш QString); Если строка из разных кодировок, то лучше оперировать QByteArray. Т.е. преобразуете ваши QString-и в нужные кодировки и результаты (ни в коем случае не преобразуя их в QString) складываете к примеру тем же самым оператором сложения. Т.е. как я писал предыдущим постом, ваша главная ошибка в присвоении результатов преобразования обратно в QString.


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: SABROG от Апрель 21, 2010, 14:19
ситуация такая что надо иметь строку состоящую из разных кодировок, причем в БД надо записать в 1251, а отправить в 866
С этого и надо было начинать. Я так понимаю клиент берет строку в 1251, переводит в 866 для передачи по сокету, сервер берет строку в 866 и перекодирует снова в 1251, а потом её кладет в базу? Или все-таки пакет может быть такого формата:

"Добавить в базу данных строку (cp866): 'ШИШ' (cp1251)" ?

Тогда определенно QByteArray или const char массив. Для сравнения:

Код:
QString str1("ШИШ"); // строка будет в Unicode кодировке (2 байта на символ) при правильно заданном кодеке
QByteArray str1("ШИШ"); // строка будет в кодировке исходника (1251 например) (1 байт на символ).
QLatin1String str2("ABC"); // строка будет в ASCII/Latin1 (1 байт на символ)
QString str3(QLatin1String("ABC")); строка будет в Unicode кодировке (преобразование latin1/ASCII (8 бит) в Unicode (16 бит)).

Код:
QLatin1String("Test"): длина 4 байта 0x54 0x65 0x73 0x74
QString(QLatin1String("Test")): длина 8 байт 0x00 0x54 0x00 0x65 0x00 0x73 0x00 0x74
QByteArray("Test"): длина 4 байта 0x54 0x65 0x73 0x74
QString(QByteArray("Test")): длина 8 байт 0x00 0x54 0x00 0x65 0x00 0x73 0x00 0x74

Ну и соответственно QString(QByteArray()) равносильно присваиванию QString = QByteArray.


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 14:28
лучше бы создатели кодировок сразу с буквой Ш вопрос решили...

http://www.getinfo.ru/article296_1.html
Что же произошло? Куда делась буква Ш? Весь фокус здесь в том, что произошла взаимокомпенсация двух ошибок. Текстовый редактор в Far по умолчанию создаёт файл в DOS-кодировке (Cp866). Компилятор же javac для чтения исходника использует file.encoding (если не указано иное ключиком -encoding). А в среде Windows с русскими региональными настройками кодировкой по умолчанию является Cp1251. Это первая ошибка. В результате, в скомпилированном файле Test.class символы имеют неверные кода. Вторая ошибка состоит в том, что для вывода используется стандартный PrintStream, который тоже использует настройку из file.encoding, однако консольное окно в Windows отображает символы, используя кодировку DOS. Если бы кодировка Cp1251 была взаимоодназначной, то потери данных бы не было. Но символ Ш в Cp866 имеет код 152, который в Cp1251 не определён, и поэтому отображается на Unicode-символ 0xFFFD. Когда происходит обратное преобразование из char в byte, вместо него подставляется символ '?'.

подскажите как правильно сложить QByteArray
делаю так, но проблема:

QString str1="ШИШ";
QByteArray ba1, ba2;

ba1="12345"+QCString(str1);
ba2="67890";
ba1=ba1+ba2; // - вот типа такой сюжет как правильно сложить???


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 21, 2010, 14:39
Буква Ш теряется в данном случае потому что у вас данные в кодировке 866 передаются кодеку 1251 и он неверно их интерпретирует.

Далее: в принципе мысль со сложением верна, но внимательно будьте с присвоением QString в QByteArray - в операторе присваивания вызывается перекодировщик и он опять может быть не тем что вам нужен. При преобразовании из QString в QByteArray лучше явно вызывать fromUnicode соответствующего кодека, раз у вас такой набор разных кодировок используется.


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 15:55
у меня qt3. там много чего нет...

подскажите как правильно сложить QByteArray
делаю так, но проблема:

QString str1="ШИШ";
QByteArray ba1, ba2;

ba1="12345"+QCString(str1);
ba2="67890";
ba1=ba1+ba2; // - вот типа такой сюжет как правильно сложить???


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 21, 2010, 16:00
Ничё не понял... в qt3 нет оператора сложения QByteArray? Что значит как правильно сложить? Напишите какие строки и в каких кодировках имеются и в каких кодировках вы хотите их сложить.


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 16:22
QString str1="ШИШ";
QByteArray ba1, ba2;

ba1="12345"+QCString(str1);
ba2="67890";
ba1=ba1+ba2; // - ВОТ ЗДЕСЬ МНЕ НАДО СЛОЖИТЬ. НА ЭТО ba1=ba1+ba2 - РУГАЕТСЯ


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: Пантер от Апрель 21, 2010, 16:41
QByteArray & QByteArray::append ( const QByteArray & ba )


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 21, 2010, 16:57
нет такого append!!!!!!!!!! у меня qt3!!!!1


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: SABROG от Апрель 21, 2010, 17:45
нет такого append!!!!!!!!!! у меня qt3!!!!1
Тогда используй QValueVector<char>.


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 22, 2010, 10:13
во блин, оказывается в qt3 fromUnicode возвращает не QByteArray, а QCString (фактически обёртка для обычных С-строк). Тогда QByteArray (а ведь и вправду не было тогда там ни operator+ ни append-а :) ) меняй на QCString - в нём есть и operator+ и append


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: vadim303 от Апрель 22, 2010, 10:15
Кстати, а чем обусловлено использование именно qt3? вроде даже в МСВС уже qt4 имеется...


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: sibmail от Апрель 22, 2010, 11:37
Начальство сказало делать на той МСВС которую мы купили, чтобы приехали, сделали qmake, make и вперед!
короче делаем на qt3.3.8 и ГИС Панорама


Название: Re: При изменении кодировки с 1251 на 866 пропадает буква Ш
Отправлено: SABROG от Апрель 22, 2010, 15:19
Я бы  изначально не пошел работать в такую контору. Изучать то, что давно не поддерживается и знания о чем никогда не пригодятся, пусть даже за это деньги были заплачены. Проект нужно постоянно обновлять и переход на Qt4 должен был начаться в тот момент, когда в Qt добавили LGPL лицензию.