Qtextcodec setcodecforcstrings qtextcodec codecforname windows 1251

QTextCodec Windows-1251 - русский QT форум
Автор Тема: QTextCodec Windows-1251  (Прочитано 9139 раз)
BuRn

Гость


Есть 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

Гость


зачем вы constData применяете? Вот в упор не вижу необходимости )


Записан
kambala


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

Гость


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

Сообщений: 4338

Просмотр профиля


_page это QString или QByteArray?
Откуда и как она заполняется?


Записан
BuRn

Гость


_page это QString или QByteArray?
Откуда и как она заполняется?

_page — QString, строка которая получилась из QByteArray в результате запроса get от NetworkAccessManager
QString content(pReply->readAll()); pReply — QNetworkReply


Записан
Old

Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4338

Просмотр профиля


_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

Гость


_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

Сообщений: 4338

Просмотр профиля


Т.е. в моем случае придется декодировать дважды ?

Если средствами кодеков Qt, то да.
Кодеки умеют конвертировать из указанной кодировки в юникод и обратно.


Записан
sociopath

Гость


Никогда не используйте неявное приведение 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

Гость


Никогда не используйте неявное приведение 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

Гость


Если используете 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.


Записан

Отображение русских символов в Qt

Отображение русских символов в Qt

Добрый день, читатель. По умолчанию русские символы в программах с использованием Qt фреймворка отображаются некорректно. Вместо них используются непонятные знаки. Эта проблема появляется при открытии исходников программ, при выводе русских букв в консоль, при выводе русских букв в виджеты (Label, PlainText и т.д.). В этой статье содержатся решения этих проблем. На сайте уже имеется статья, в которой показано решение проблемы отображения русских букв при выводе в консоль на C++.

Русские символы в исходном коде

Бывает возникает проблема с кодировкой при открытии исходных текстов программ в Qt Creator, чаще всего такая проблема возникает у пользователей Windows. Дело в том, что при написании программы исходники иногда сохраняются в одной кодировке, а редактор в Qt Creator открывает по умолчанию в другой кодировке. Из-за этого вместо русских букв появляются кракозябры или знаки вопроса. По умолчанию в настройках редактора кода Qt Creator кодировка файлов устанавливается System, т.е. кодировка операционной системы. Linux чаще всего использует UTF-8, а Windows cp1251.

Проблема с кодировкой в редакторе Qt Creator

Проблема с кодировкой в редакторе Qt Creator

Для решения проблемы в верхнем меню Qt Creator следует выбрать Инструменты(Tools) — Параметры…(Settings…). В открывшемся окне слева в списке найти и выбрать Текстовый редактор(Text Editor), далее выбираем вкладку Поведение(Behavior). Находим группу настроек Кодировки файлов(Encoding files) и выбираем кодировку по умолчанию(default) — UTF-8. Теперь редактор будет открывать исходники в UTF-8, исходные тексты программ чаще всего пишутся именно в этой кодировке.

После настройки редактора следует перекодировать сами исходники. Это можно сделать в Notepad++, если вы пользователь Windows.

Можно открывать файлы и в других кодировках, для этого в верхнем меню следует выбрать Правка — Выбрать кодировку, а далее найти кодировку, в которой был сохранен исходник программы.

В итоге редактор будет сохранять исходники в новых проектах в UTF-8 и корректно открывать их после.

Помещая русские символы в поле Text в виджете Label или в другие виджеты, можно также столкнуться с проблемой отображения русских букв. В редакторе форм русские символы в виджеты устанавливаются и отображаются нормально, а вот при установки программным путем — нет.

Поместим русские символы в виджет Label и в PushButton в редакторе форм.

Русские символы в редакторе форм Qt

Русские символы в редакторе форм Qt

Как видно, они отображаются корректно. Далее скомпилируем и запустим программу.

Отображение русских символов в виджетах

Отображение русских символов в виджетах

Отображение символов корректно. Теперь в изменим текст в виджетах программным путем, для этого в редакторе кода в файле mainwindow.cpp в конструктор добавим пару строк:

    ui->label->setText("Русские символы");
    ui->pushButton->setText("И здесь");

А затем скомпилируем и запустим программу.

Проблемы с отображением русских символов

Проблемы с отображением русских символов

Как видно, проблема имеет место быть, но решить ее очень легко.

Для этого устанавливаем текст с помощью функции trUtf8().

    ui->label->setText(trUtf8("Русские символы"));
    ui->pushButton->setText(trUtf8("И здесь"));

Скомпилируем и запустим программу.

Корректное отображение с trUtf8()

Корректное отображение с trUtf8()

Проблема решена, но если таких выводов в программе много, то вставка текста через функцию нерациональна с точки зрения времени. Можно решить проблему не прибегая к функции trUtf8(), для этого нужно лишь задать кодеки в программе. В файле main.cpp подключаем заголовок QTextCodec.

#include <QTextCodec>

В начало функции main.cpp добавляем следующие строчки:

    QTextCodec* codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForTr(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForLocale(codec);

Устанавливаем текст в виджетах в файле mainwindow.cpp без функции trUtf8()

    ui->label->setText("Русские символы");
    ui->pushButton->setText("И здесь");

Компилируем и запускаем.

Корректное отображение русских символов с установленным кодеком

Корректное отображение русских символов с установленным кодеком

Отображение символов корректно, теперь не нужно прибегать к функции trUtf8(). Проблема решена.

Кстати, в последних версиях Qt такой проблемы с кодировкой у меня не наблюдалось.

Для примера был создан стандартный проект Qt Widgets. Поэтому после решения проблем с кодировкой файл main.cpp содержит следующий код

#include "mainwindow.h"
#include <QApplication>
#include <QTextCodec>

int main(int argc, char *argv[])
{
    QTextCodec* codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForTr(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForLocale(codec);
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Вывод русских символов в консоль с Qt

Если русские символы в консоль выводятся некорректно через qDebug(), то решение для этого такое же, как и решение с отображением русских символов в виджетах Qt.

А если Вы пишете без Qt и у вас проблемы русскими символами при выводе в консоль, то почитайте статью, там есть решение — Русские символы(буквы) при вводе/выводе в консоль на C++.

Надеюсь, что статья Вам чем-то помогла.

Спасибо за внимание.

alt text

задан 15 фев 2015 в 9:09

perfect's user avatar

perfectperfect

9,92113 золотых знаков50 серебряных знаков109 бронзовых знаков

5

Доброго времени суток!

Ваше решение не самое лучшее — в Qt 5 оно не будет работать, поскольку в Qt 5 отсутствует статический метод QTextCodec::setCodecForTr() (http://doc.qt.io/qt-5/qtextcodec.html).

Разработчики Qt советуют перевести все исходные файлы проекта в кодировку UTF-8, и проблема исчезнет сама собой)

Успехов!

ответ дан 24 фев 2015 в 20:21

progzdeveloper's user avatar

2

Победил следующим образом:

  1. Заходим Инструменты->Параметры->Текстовый редактор->По умолчанию->Кодировки файлов->По умолчанию — устанавливаем windows-1251
  2. Добавляем заголовок #include <QTextCodec>
  3. В самом начале функции main пишем следующее

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName(«CP1251»));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName(«CP1251»));
    QTextCodec::setCodecForTr(QTextCodec::codecForName(«CP1251»));

  4. все работает

alt text

ответ дан 15 фев 2015 в 13:52

perfect's user avatar

perfectperfect

9,92113 золотых знаков50 серебряных знаков109 бронзовых знаков

Для Qt6 и проектов CMake простое элегантное решение:

  1. Добавляем в конец файла CMakeLists.txt строку:
    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${PROJECT_SOURCE_DIR}/decode.bat")
    
  2. Помещаем текстовый файл decode.bat в папку, где лежит CMakeLists.txt с содержимым:
    @chcp 1251 >nul
    
    @call %*
    

0xdb's user avatar

0xdb

51.2k194 золотых знака56 серебряных знаков227 бронзовых знаков

ответ дан 20 янв 2021 в 23:53

Евгений's user avatar

Вывод кириллицы в консоли QT5

Распространённая у новичков проблема :) Следует понимать, что QT – кроссплатформенный продукт. Удовлетворительного решения для вывода кириллицы именно в консоли Windows (в отличие от Linux) нет. В QT5 можно попробовать:

QTextCodec *coding = QTextCodec::codecForName("utf-8");
coding->setCodecForLocale(coding);

или

system("chcp 65001");

если ваши файлы в Юникоде (UTF-8). Соответственно, "cp-1251" и "chcp 1251" для российской кодировки Windows. Сам текст файла .cpp, конечно же, тоже должен быть сохранён в нужной кодировке.

Популярное в сети решение с вызовом setCodecForCStrings и setCodecForTr работало только до QT4 включительно. А лучше делать свою консоль на основе QTextEdit, кроме работы с кодировками, будут возможности для оформления. Кроме того, для написания современных приложений следует, в общем случае, предпочитать Юникод.

Консольное приложение может быть реализовано и без использования класса QCoreApplication. В этом случае работа со стандартной консолью Windows возможна следующим образом:

#include <QTextStream>
#include <conio.h>

int main() {
 QTextStream cin(stdin); cin.setCodec("CP866");
 QTextStream cout(stdout); cout.setCodec("CP866");
 cout << QString::fromUtf8("Введите ваше имя: ");
 cout.flush();
 QString name;
 cin >> name;
 cout << QString::fromUtf8("Привет, ") <<
         name <<
         QString::fromUtf8("!") << endl;
 return 0;
}

Проверено в Windows 7 + QT5.2.1, сработало. Обратите внимание, что кодировка консоли здесь именно CP866 (DOS), как и было для DOS-приложений.

Кроме того, можно пользоваться стандартными возможностями C++ (setlocale)

P.S. В более новых сборках QT 5 со средой Creator 4.X приходилось также указывать CP866 только для ввода, а для вывода CP1251 (пример кода для консоли QT 5 показан ниже), менять шрифт, назначенный для консольных приложений и т.п. В целом, думаю, на проблеме зацикливаться не стоит, все ваши реальные приложения всё равно будут не-консольными и в UTF-8 :)

#include <iostream>
#include <QTextStream>
using namespace std;

int main() {
 setlocale(LC_ALL, "Rus");
 QTextStream cin(stdin); cin.setCodec("CP866");
 QTextStream cout(stdout); cout.setCodec("CP1251");

 QString name;
 cout << QString::fromUtf8("Как Вас зовут? ") << endl;
 cin >> name;
 cout << QString::fromUtf8("Привет, ") << name << "!";

 return 0;
}

02.02.2016, 17:24 [13816 просмотров]


К этой статье пока нет комментариев, Ваш будет первым

Понравилась статья? Поделить с друзьями:
  • Qtcore4 dll скачать для windows 7 бесплатно
  • Qtcore4 dll скачать для windows 7 x64
  • Qt5xml dll скачать 64 bit windows 10
  • Qt5winextras dll скачать 64 bit windows 10
  • Qt5widgets dll скачать 64 bit windows 10 x64