Преобразование QString в QByteArray с кодировкой UTF-8 или Latin1
Я хотел бы скрыть QString в utf8 или latin1 QByteArray, но сегодня я получаю все, как utf8.
и я тестирую это с некоторым char в более высоком сегменте latin1 выше 0x7f, где немецкий ü-хороший пример.
если мне это нравится:
QString name("u00fc"); // U+00FC = ü
QByteArray utf8;
utf8.append(name);
qDebug() << "utf8" << name << utf8.toHex();
QByteArray latin1;
latin1.append(name.toLatin1());
qDebug() << "Latin1" << name << latin1.toHex();
QTextCodec *codec = QTextCodec::codecForName("ISO 8859-1");
QByteArray encodedString = codec->fromUnicode(name);
qDebug() << "ISO 8859-1" << name << encodedString.toHex();
я получаю следующий вывод.
utf8 "ü" "c3bc"
Latin1 "ü" "c3bc"
ISO 8859-1 "ü" "c3bc"
как вы можете видеть, я получаю unicode 0xc3bc везде, где я ожидал бы получить Latin1 0xfc для Шаг 2 и 3.
Я предполагаю, что я должен получить что-то вроде этого:
utf8 "ü" "c3bc"
Latin1 "ü" "fc"
ISO 8859-1 "ü" "fc"
что здесь происходит?
/спасибо
ссылки на некоторые таблицы символов:
этот код был построен и выполнен на основе Ubuntu 10.04 система.
$> uname -a
Linux frog 2.6.32-28-generic-pae #55-Ubuntu SMP Mon Jan 10 22:34:08 UTC 2011 i686 GNU/Linux
$> env | grep LANG
LANG=en_US.utf8
и если я пытаюсь использовать
utf8.append(name.toUtf8());
я получаю этот выход
utf8 "ü" "c383c2bc"
Latin1 "ü" "c3bc"
ISO 8859-1 "ü" "c3bc"
таким образом, latin1 является unicode, а utf8-двойным...
это должно зависеть от того, какие параметры системы?
если я запустил это (не удалось получить .name () to build)
qDebug() << "system name:" << QLocale::system().name();
qDebug() << "codecForCStrings:" << QTextCodec::codecForCStrings();
qDebug() << "codecForLocale:" << QTextCodec::codecForLocale()->name();
тогда я получаю это:
system name: "en_US"
codecForCStrings: 0x0
codecForLocale: "System"
решение
если я укажу, что это UTF-8 I я использую, чтобы разные классы знали об этом, тогда это работает.
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
qDebug() << "system name:" << QLocale::system().name();
qDebug() << "codecForCStrings:" << QTextCodec::codecForCStrings()->name();
qDebug() << "codecForLocale:" << QTextCodec::codecForLocale()->name();
QString name("u00fc");
QByteArray utf8;
utf8.append(name);
qDebug() << "utf8" << name << utf8.toHex();
QByteArray latin1;
latin1.append(name.toLatin1());
qDebug() << "Latin1" << name << latin1.toHex();
QTextCodec *codec = QTextCodec::codecForName("latin1");
QByteArray encodedString = codec->fromUnicode(name);
qDebug() << "ISO 8859-1" << name << encodedString.toHex();
затем я получаю этот выход:
system name: "en_US"
codecForCStrings: "UTF-8"
codecForLocale: "UTF-8"
utf8 "ü" "c3bc"
Latin1 "ü" "fc"
ISO 8859-1 "ü" "fc"
и похоже, что так и должно быть.
1 ответов
что нужно знать:
- страница символов выполнения
есть что-то под названием исполнение набор символов в стандарте C++, который является термином, описывающим, что выход строковых и символьных литералов будет в двоичном файле, производимом компилятором. Вы можете прочитать об этом в 1.1 наборы символов подраздел 1 Обзор на руководство препроцессора C на http://gcc.gnu.org сайт.
вопрос:
Что будет произведено в результате "\u00fc"
строковый литерал?
ответ:
Это зависит от того, что такое набор символов выполнения. В случае gcc (который вы используете) это по умолчанию UTF-8, Если вы не укажете что-то другое с . Вы можете прочитать об этом и других параметрах, контролирующих фазу предварительной обработки в 3.11 параметры управления Препроцессор подраздел 3 опции команды GCC на руководство GCC on http://gcc.gnu.org сайт. Теперь, когда мы знаем, что набор символов выполнения-UTF-8, мы знаем, что "\u00fc"
будет переведено на кодировку UTF-8 U+00FC
кодовая точка Unicode, которая представляет собой последовательность из двух байтов 0xc3 0xbc
.
-
QString::QString ( const char * str )
иQByteArray & QByteArray::append ( const QString & str )
зависит от глобального состояния
в Конструктор QString принимает char *
звонки QString QString::fromAscii ( const char * str, int size = -1 )
который использует набор кодеков с void QTextCodec::setCodecForCStrings ( QTextCodec * codec )
(если кодек установлен), или делает то же самое как QString QString::fromLatin1 ( const char * str, int size = -1 )
(если кодек не был установлен).
вопрос:
Какой кодек будет использоваться конструктором QString для декодирования двухбайтовой последовательности (0xc3 0xbc
) он получает?
ответ:
По умолчанию кодек не имеет значения QTextCodec::setCodecForCStrings()
вот почему Latin1 будет использоваться для декодирования последовательность байтов. As 0xc3
и 0xbc
оба действительны на латыни 1, представляя соответственно Ã и ¼ (это уже должно быть знакомо вам, поскольку оно было взято непосредственно из этой ответ на ваш предыдущий вопрос) мы получаем QString с этими двумя символами.
-
qDebug()
не 8-битный чистый
вы не должны использовать QDebug
класс для вывода чего-либо вне ASCII. У тебя нет гарантии, что ты ... получить.
тестовая программа:
#include <QtCore>
void dbg(char const * rawInput, QString s) {
QString codepoints;
foreach(QChar chr, s) {
codepoints.append(QString::number(chr.unicode(), 16)).append(" ");
}
qDebug() << "Input: " << rawInput
<< ", "
<< "Unicode codepoints: " << codepoints;
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
qDebug() << "system name:"
<< QLocale::system().name();
for (int i = 1; i <= 5; ++i) {
switch(i) {
case 1:
qDebug() << "\nWithout codecForCStrings (default is Latin1)\n";
break;
case 2:
qDebug() << "\nWith codecForCStrings set to UTF-8\n";
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
break;
case 3:
qDebug() << "\nWithout codecForCStrings (default is Latin1), with codecForLocale set to UTF-8\n";
QTextCodec::setCodecForCStrings(0);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
break;
case 4:
qDebug() << "\nWithout codecForCStrings (default is Latin1), with codecForLocale set to Latin1\n";
QTextCodec::setCodecForCStrings(0);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("Latin1"));
break;
}
qDebug() << "codecForCStrings:" << (QTextCodec::codecForCStrings()
? QTextCodec::codecForCStrings()->name()
: "NOT SET");
qDebug() << "codecForLocale:" << (QTextCodec::codecForLocale()
? QTextCodec::codecForLocale()->name()
: "NOT SET");
qDebug() << "\n1. Using QString::QString(char const *)";
dbg("\u00fc", QString("\u00fc"));
dbg("\xc3\xbc", QString("\xc3\xbc"));
dbg("LATIN SMALL LETTER U WITH DIAERESIS", QString("ü"));
qDebug() << "\n2. Using QString::fromUtf8(char const *)";
dbg("\u00fc", QString::fromUtf8("\u00fc"));
dbg("\xc3\xbc", QString::fromUtf8("\xc3\xbc"));
dbg("LATIN SMALL LETTER U WITH DIAERESIS", QString::fromUtf8("ü"));
qDebug() << "\n3. Using QString::fromLocal8Bit(char const *)";
dbg("\u00fc", QString::fromLocal8Bit("\u00fc"));
dbg("\xc3\xbc", QString::fromLocal8Bit("\xc3\xbc"));
dbg("LATIN SMALL LETTER U WITH DIAERESIS", QString::fromLocal8Bit("ü"));
}
return app.exec();
}
вывод на mingw 4.4.0 в Windows XP:
system name: "pl_PL"
Without codecForCStrings (default is Latin1)
codecForCStrings: "NOT SET"
codecForLocale: "System"
1. Using QString::QString(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
2. Using QString::fromUtf8(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
3. Using QString::fromLocal8Bit(char const *)
Input: \u00fc , Unicode codepoints: "102 13d "
Input: \xc3\xbc , Unicode codepoints: "102 13d "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
With codecForCStrings set to UTF-8
codecForCStrings: "UTF-8"
codecForLocale: "System"
1. Using QString::QString(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
2. Using QString::fromUtf8(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
3. Using QString::fromLocal8Bit(char const *)
Input: \u00fc , Unicode codepoints: "102 13d "
Input: \xc3\xbc , Unicode codepoints: "102 13d "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
Without codecForCStrings (default is Latin1), with codecForLocale set to UTF-8
codecForCStrings: "NOT SET"
codecForLocale: "UTF-8"
1. Using QString::QString(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
2. Using QString::fromUtf8(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
3. Using QString::fromLocal8Bit(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
Without codecForCStrings (default is Latin1), with codecForLocale set to Latin1
codecForCStrings: "NOT SET"
codecForLocale: "ISO-8859-1"
1. Using QString::QString(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
2. Using QString::fromUtf8(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
3. Using QString::fromLocal8Bit(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
codecForCStrings: "NOT SET"
codecForLocale: "ISO-8859-1"
1. Using QString::QString(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
2. Using QString::fromUtf8(char const *)
Input: \u00fc , Unicode codepoints: "fc "
Input: \xc3\xbc , Unicode codepoints: "fc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fffd "
3. Using QString::fromLocal8Bit(char const *)
Input: \u00fc , Unicode codepoints: "c3 bc "
Input: \xc3\xbc , Unicode codepoints: "c3 bc "
Input: LATIN SMALL LETTER U WITH DIAERESIS , Unicode codepoints: "fc "
спасибо Тьяго, cbreak, Пеппе и Гейнц из #qt freenode.org IRC канал для показа и помогает мне понять проблемы, связанные здесь.