Russian Qt Forum
Октябрь 10, 2024, 13:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QTextCodec Windows-1251  (Прочитано 11132 раз)
BuRn
Гость
« : Март 08, 2015, 16:35 »

Есть html страница, в ней явно указано "charset=windows-1251". Пытаюсь преобразовать в utf8 QString, на выходе получаю лажу, выглядит это как-то
Код:
QTextCodec* defaultTextCodec = QTextCodec::codecForName("Windows-1251");
QTextCodec::codecForHtml(_page.toLatin1().constData(), defaultTextCodec);
QString page = htmlTextCodec->toUnicode(_page.toLatin1().constData());
Пробовал и так, результат тоже не удовлетворительный
Код:
QString page = QTextCodec::codecForName("Windows-1251")->toUnicode(_page.toLatin1());
Записан
Bepec
Гость
« Ответ #1 : Март 08, 2015, 17:55 »

зачем вы constData применяете? Вот в упор не вижу необходимости )
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #2 : Март 08, 2015, 18:49 »

1. toLatin1() убьет всю кириллицу, используй toLocal8Bit() например или через кодек
2. QString — это UTF-16, а не 8
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
BuRn
Гость
« Ответ #3 : Март 08, 2015, 19:02 »

1. toLatin1() убьет всю кириллицу, используй toLocal8Bit() например или через кодек
2. QString — это UTF-16, а не 8
Опять делаю что-то не так? но в строках по прежнему лажа
Код:
    QTextCodec* defaultTextCodec = QTextCodec::codecForName("Windows-1251");
    QTextCodec* htmlTextCodec = QTextCodec::codecForHtml(_page.toLocal8Bit(), defaultTextCodec);

    QString page = htmlTextCodec->toUnicode(_page.toLocal8Bit());
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Март 08, 2015, 19:08 »

_page это QString или QByteArray?
Откуда и как она заполняется?
Записан
BuRn
Гость
« Ответ #5 : Март 08, 2015, 19:16 »

_page это QString или QByteArray?
Откуда и как она заполняется?
_page - QString, строка которая получилась из QByteArray в результате запроса get от NetworkAccessManager
QString content(pReply->readAll()); pReply - QNetworkReply
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Март 08, 2015, 19:26 »

_page - QString, строка которая получилась из QByteArray в результате запроса get от NetworkAccessManager
QString content(pReply->readAll()); pReply - QNetworkReply
Вот не надо таких преобразований. Улыбающийся
Вам нужно два кодека, один W-1251, второй UTF-8.
Вначале, вы делаете QByteArray toUnicode с кодеком W-1251, получаете QString. Дальше вы делаете этой строке fromUnicode с кодеком UTF-8, получаете QByteArray в которой данные в utf8.
Записан
BuRn
Гость
« Ответ #7 : Март 08, 2015, 19:37 »

_page - QString, строка которая получилась из QByteArray в результате запроса get от NetworkAccessManager
QString content(pReply->readAll()); pReply - QNetworkReply
Вот не надо таких преобразований. Улыбающийся
Вам нужно два кодека, один W-1251, второй UTF-8.
Вначале, вы делаете QByteArray toUnicode с кодеком W-1251, получаете QString. Дальше вы делаете этой строке fromUnicode с кодеком UTF-8, получаете QByteArray в которой данные в utf8.
Т.е. в моем случае придется декодировать дважды ?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Март 08, 2015, 19:49 »

Т.е. в моем случае придется декодировать дважды ?
Если средствами кодеков Qt, то да.
Кодеки умеют конвертировать из указанной кодировки в юникод и обратно.
Записан
sociopath
Гость
« Ответ #9 : Март 10, 2015, 11:08 »

Никогда не используйте неявное приведение QByteArray к QString для не ascii-символов (кириллицы и пр.). В Qt4 это преобразование делается через функцию fromAscii, которая в свою очередь использует либо QTextCodec::codecForCStrings, либо Latin1. В Qt5 это преобразование делается через функцию fromUtf8.
Всегда следует явно указывать кодировку, в которую хотите привести массив байтов.
Результат pReply->readAll() в виде QByteArray нужно тащить до момента, когда известен кодек, и уже тогда декодировать в QString (если кодек известен при pReply->readAll(), значит сразу после этого и декодировать).

Делать что-то типа:
Код:
QByteArray ba = pReply->readAll();
QTextCodec* defaultTextCodec = QTextCodec::codecForName("Windows-1251");
QString page = defaultTextCodec->toUnicode(ba);
Записан
BuRn
Гость
« Ответ #10 : Март 10, 2015, 11:57 »

Никогда не используйте неявное приведение QByteArray к QString для не ascii-символов (кириллицы и пр.). В Qt4 это преобразование делается через функцию fromAscii, которая в свою очередь использует либо QTextCodec::codecForCStrings, либо Latin1. В Qt5 это преобразование делается через функцию fromUtf8.
Всегда следует явно указывать кодировку, в которую хотите привести массив байтов.
Результат pReply->readAll() в виде QByteArray нужно тащить до момента, когда известен кодек, и уже тогда декодировать в QString (если кодек известен при pReply->readAll(), значит сразу после этого и декодировать).

Делать что-то типа:
Код:
QByteArray ba = pReply->readAll();
QTextCodec* defaultTextCodec = QTextCodec::codecForName("Windows-1251");
QString page = defaultTextCodec->toUnicode(ba);
Не, сделал по другому, это класс используется вообщем для получения web страницы, а страницы бывают в разных кодировках, ваш вариант тоже от части не корректен. Сделал через codecForHtml, проверил на нескольких сайтах с разными кодировками, определяет корректно
Записан
sociopath
Гость
« Ответ #11 : Март 10, 2015, 12:57 »

Если используете Qt5, то скорее всего codecForHtml правильно определит кодировку:
Код:
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
    // determine charset
    QTextCodec *c = QTextCodec::codecForUtfText(ba, 0);
    if (!c) {
        QByteArray header = ba.left(1024).toLower();
        int pos = header.indexOf("meta ");
        if (pos != -1) {
            pos = header.indexOf("charset=", pos);
            if (pos != -1) {
                pos += qstrlen("charset=");
                int pos2 = pos;
                // The attribute can be closed with either """, "'", ">" or "/",
                // none of which are valid charset characters.
                while (++pos2 < header.size()) {
                    char ch = header.at(pos2);
                    if (ch == '\"' || ch == '\'' || ch == '>') {
                        QByteArray name = header.mid(pos, pos2 - pos);
                        if (name == "unicode") // QTBUG-41998, ICU will return UTF-16.
                            name = QByteArrayLiteral("UTF-8");
                        c = QTextCodec::codecForName(name);
                        return c ? c : defaultCodec;
                    }
                }
            }
        }
    }
    if (!c)
        c = defaultCodec;
    return c;
}

А вот в Qt4.8 очень слабенькая реализация (HTML5 стандарт определения кодировки не поддерживает):
Код:
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
    // determine charset
    int pos;
    QTextCodec *c = 0;

    c = QTextCodec::codecForUtfText(ba, c);
    if (!c) {
        QByteArray header = ba.left(512).toLower();
        if ((pos = header.indexOf("http-equiv=")) != -1) {
            if ((pos = header.lastIndexOf("meta ", pos)) != -1) {
                pos = header.indexOf("charset=", pos) + int(strlen("charset="));
                if (pos != -1) {
                    int pos2 = header.indexOf('\"', pos+1);
                    QByteArray cs = header.mid(pos, pos2-pos);
                    //            qDebug("found charset: %s", cs.data());
                    c = QTextCodec::codecForName(cs);
                }
            }
        }
    }
    if (!c)
        c = defaultCodec;

    return c;
}

Если используете Qt4, очень советую вставить реализацию из Qt5.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.153 секунд. Запросов: 23.