MS SQL (Win1251) --(?)--> Qt (Unicode)

    Небольшой хак по преобразованию кодировки windows-1251 в MSSQL в Unicode для Qt5.

    Есть еще системы, которые используют mssql в кодировке win. К одной такой системе я написал расширение на Qt4 и проблему с русскими буквами решил просто: сменой кодировки
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("Windows-1251"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("Windows-1251"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("Windows-1251"));
    

    Время идет и я по возможности перевожу свои проекты на Qt5. Однако, там команды смены кодеков убрали. Все должно быть в Unicode, что правильно. Да и решение работало не всегда и не на каждой версии ОС win.

    В своей программе я напрямую не отображаю результат SQL запроса в модель, поэтому проблему решил пока так:

    //подключение к бд
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setUserName("<username>");
    db.setPassword("<userpass>");
    db.setDatabaseName("DRIVER={SQL Server};Server=<servername>;Database=<databasename>;Regional=Yes");
    
    //скорректировал SQL-запрос, в части полей с русскими буквами
    query->exec( "select cast(<fieldname> as varbinary) from <tablename>");
    
    //кодек для преобразования
    QTextCodec *codec = QTextCodec::codecForName("Windows-1251");
    
    //беру содержимое поля как массив байт и преобразовываю его к Unicode. Дальше его можно использовать в Qt
    ... = codec->toUnicode(queryl->value( 0 ).toByteArray());
    


    Интересно, что если поле не преобразовывать к varbinary, то метод .toByteArray() выдаст уже испорченные данные.

    А может кто-то знает строку подключения для данных в Unicode?
    Поделиться публикацией
    Комментарии 8
      +5
      QT — Quick Time
      Qt — Create more. Deploy everywhere.
        +1
        По-моему у Qt внутри был UTF-16, или в последнее время что-то стало меняться?
          +1
          QString использует UTF-16 (последовательность 16-битных QChar), почему должно что-то меняться? Внутреннее представление строк никакого отношения к тому что написано в посте не имеет же. В большинстве сред/платформ юникод внутри в UTF-16/UCS2/UTF-32.
            +1
            Автор поменял текст поста, теперь мой вопрос выглядит неуместным. Меня удивило, почему именно 1251 -> UTF-8.
              0
              Я исправил текст поста. Спасибо за ваши комментарии!
                0
                Я, может, чего-то не понял (не работал с mssql из Qt), но вообще ситуация какая-то странная. Для работы с БД на уровне строк всё должно быть прозрачно (как это прозрачно в ODBC, JDBC и подобном где я сталкивался) в какой бы кодировке реально не хранилось в самой БД. Это должно решаться не далее уровня клиента БД. Это имеет значение, только если читать из строковых полей сырые данные. Тогда да, вы получите байтовое представление значения столбца (строки в нём) в кодировке представления столбца. Но именно это вы и делаете зачем-то (toByteArray как я понимаю).
                  0
                  Вот именно, что должно быть прозрачно.
                  Для доступа к mysql есть строки подключения по unicode.
                  Driver={MySQL ODBC 5.2 UNICODE Driver};...
                  

                  Для Pg
                  Driver={PostgreSQL UNICODE}
                  

                  И так далее, но найти строку подключения к MSSQL с юникодом найти не удалось. Народ пытается работать через FreeTDS, но оно под unix. Пишет невероятные преобразования, в php использует iconv. В документации QT написано про Some driver managers and drivers don't support UNICODE.
                  Это имеет значение, только если читать из строковых полей сырые данные. Тогда да, вы получите байтовое представление значения столбца (строки в нём) в кодировке представления столбца. Но именно это вы и делаете зачем-то (toByteArray как я понимаю).

                  Мои исследования показали, что если читать toByteArray в Qt 4-й ветке, то там как раз и будут сырые данные. Но в Qt5 это уже не так. Сам в этом убедился и на данной задаче и на задаче с доступом к paradox.
                    0
                    А… ну понятно. Вот я и думаю, что по идее на уровне коннекта должно это определяться. Странно поэтому.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое