IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Discussion :

Les caractères spéciaux éèû ne fonctionnent pas pour un SELECT (en ISO-8859-1)


Sujet :

Bases de données

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 9
    Points : 3
    Points
    3
    Par défaut Les caractères spéciaux éèû ne fonctionnent pas pour un SELECT (en ISO-8859-1)
    Bonjour tout le monde,

    Je me décide à poster car je n'arrive pas à trouver une réponse à mon problème malgré le fait que cela fait plusieurs jours que je recherche une solution. Et bien sur il faut absolument que j'arrive à résoudre ce problème (sinon je ne serais pas la ^^)
    Je travaille sous Qt creator 2.4.1 basé sur QT 4.7.4 (sous win 7), pour lire dans une base de données SQL (en 2008 R2). La base de données est celle de notre gestion commerciale "sage 100". Je travaille qu'en lecture sur cette bdd, aucune insertion. Utilisation du driver SQL Native Client 10.0 pour le DSN.

    Mon problème est lorsque je fais un 'select', le résultat retourné m'affiche des caractères '?' au lieu des caractères spéciaux 'éèî' etc. Tous les autres caractères s'affichent correctement. Les caractères qui posent problème sont ceux faisant partis de caractères étendus ASCII (cf: http://www.asciitable.com/ )

    Voici une partie du code utilisé dans ma classe:

    dans le .h mes variables:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QSqlQuery *maQuery ;
     QString reponseReq ;
     QSqlDatabase maDb ;

    dans le cpp, ma fonction de connection à ma base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    maDb = QSqlDatabase::addDatabase("QODBC");
     qDebug() << maDb.isValid();
     maDb.setHostName("serveur3");
     maDb.setDatabaseName("gecotesttt");
     maDb.setUserName("admin");
     maDb.setPassword("XXX");
     maQuery = new QSqlQuery ;

    toujours ds le cpp, ma fonction d'execution de la requête (le select est allégé ici)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    maQuery->prepare("SELECT F_DOCENTETE.DO_Piece,  F_LIVRAISON.LI_Adresse, F_LIVRAISON.LI_Telephone, F_COMPTET.CT_EMail, F_DOCENTETE.DO_Type FROM F_DOCENTETE FULL OUTER JOIN F_LIVRAISON ON F_DOCENTETE.LI_No = F_LIVRAISON.LI_No FULL OUTER JOIN F_COMPTET ON F_LIVRAISON.CT_Num = F_COMPTET.CT_Num WHERE F_DOCENTETE.DO_Piece = :premierevaleur AND F_DOCENTETE.DO_Type = :deuxiemevaleur") ;
     
     
      maQuery->bindValue(":premierevaleur", numDoc);
      maQuery->bindValue(":deuxiemevaleur", choixTypeDocument);
     
     
       ...
     
                 while(maQuery->next())
                  {
     
                      for(int x=0; x < maQuery->record().count(); ++x)
                      {
                          reponseReq = maQuery->value(x).toString();
                          qDebug() << "Dans CBaseDeDonnées.cpp" << reponseReq ;
                      }                     
           ...
     
         }


    Ce que j'ai déja tenté:
    - J'ai modifié l'encodage de mes pages de code en choisisant "UTF-8".

    - J'ai bien inscrit ces 3 lignes dans le main:
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

    - J'ai recherché à définir une option pour la connection à ma base en définissant l'encodage de ma base mais je n'ai rien trouvé.

    - de transformer le resultat de ma variable QSqlQuery (mais à chaque fois des erreurs de compilations apparaissent...)

    - j'ai essayé d'utiliser la fonction "COLLATE" dans ma requete, mais le resultat obtenu ne corrige pas mon probleme. (COLLATE Latin1_General_BIN ou autre)


    Autre remarque:
    - je ne peux pas modifier directement l'encodage de ma base de données puisqu'elle est créée et remplie par un logiciel tiers. D'après ce que j'ai trouvé elle est en ISO-8859-1. Avec classement FRENCH_CI_AS
    - Les données dans ma base de données sont bien encodées puisque si j'y accède par access excel ou autres, mes accents apparaissent correctement...
    - suivant l'encodage, en mode debug, mes accents apparaissent soient en '?' ou alors en '177775'.

    Merci de m'avoir lu. Toutes propositions / idées / questions sera accepté avec grand plaisir car la je ne sais plus du tout quoi faire...
    merci de vos réponses !

  2. #2
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonsoir,

    Avez-vous essayé ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    reponseReq = QString::fromLatin1(qPrintable(maQuery->value(x).toString()));
    Dans le sens où votre fichier attend de l'UTF8 pour que l'encodage soit correct et que la BDD retourne de l'ISO, j'aurais tendance à partir là-dessus.

    Pour les erreurs de compilation, il doit y avoir moyen d'arranger ça, si les idées associées vous semblent justifiées. Si c'est le cas, je vous invite à détailler ces éléments.

    Vérifiez également si l'encodage est réellement de l'ISO-8859-1 et pas de l'ISO-8859-15, par exemple.

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Tout d'abord un grand merci pour vous intéresser a mon problème car, il faut le dire, je suis dépassé ! Mais j'apprends !! ^^

    Ensuite j'ai essayé d'insérer la fonction fromString comme proposé mais le résultat est que je n'ai plus des '?' mais des '�'. Donc ma base est peut etre en iso-8859-15. J'ai demandé à mon prestataire qui nous vend ce logiciel et ils ne veulent pas me donner l'encodage de la base ! du coup je ne peux faire que des suppositions...

    Pour mes erreurs de compilation, vous m'avez deja donné une réponse car j'avais essayé d'utiliser la fonction proposée (fromlatin1) mais je n'utilisais pas 'qprintable', donc forcement ca ne pouvait pas se compiler...

    Enfin je ne sais pas qu'elle est la bonne méthode pour avoir mes accents, j'ai essayé pas mal de choses différentes mais sans résultat.
    La dernière chose que j'ai tenté c'est de me connecter avec cette fonction en remplacant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    maDb.setHostName("serveur3");
     maDb.setDatabaseName("gecotesttt");
     maDb.setUserName("administrateur");
     maDb.setPassword("xxx");
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    maDb.setDatabaseName("driver={SQL Server Native Client 10.0};server=SERVEUR3;uid=administrateur;pwd=xxx;database=gecotest;Trusted_Connection=yes;CharSet=ISO_8859_15") ;

    j'espérais que l'option 'CharSet=ISO_8859_15' fonctionnerais mais ce n'est pas le cas (j'ai essayé plusieurs syntaxes pour iso_8859_1 mais peut etre jamais la bonne). Ma connection se deroule bien mais toujours ce problème de caractères spéciaux...

    Bref je suis perdu, si vous avez la possibilité de me proposer quelque chose, une piste, une idée ou une baguette magique, quelque soit la méthode tant que cela fonctionne, je vous en serais vraiment reconnaissant...
    merci de m'avoir lu

    cordialement

  4. #4
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonsoir,

    Quelques petites lignes à tester :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    qDebug() << maDb.driver()->hasFeature(QSqlDriver::Unicode);
    S'il renvoie false, il y a sans doute un problème quelque part.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    reponseReq = QString::fromUtf8(qPrintable(maQuery->value(x).toString()));
    On peut toujours tenter.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QTextCodec *codec = QTextCodec::codecForName("ISO 8859-15");
    reponseReq  = QString(codec->fromUnicode(maQuery->value(x).toString()));
    Cela permettra de vérifier si on a plus de chance avec l'ISO 8859-15. Il faudrait tout de même tenter de trouver une requête à lancer pour récupérer l'encodage réel, cela permettrait de faire avancer les choses.

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    bonsoir et merci de la réponse !

    donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    qDebug() << maDb.driver()->hasFeature(QSqlDriver::Unicode);
    me retourne false

    j'ai donc cherché l'encodage de ma base et vous aviez raison je suis bien en iso-8859-15:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT name, collation_name FROM sys.databases;
    -> French_CI_AS
    Ensuite j'ai cherché à utilisé votre code proposé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QTextCodec *codec = QTextCodec::codecForName("ISO 8859-15");
    reponseReq  = QString(codec->fromUnicode(maQuery->value(x).toString()));
    mais le problème persiste toujours.

    Après réflexion je me suis dit (a tort ou à raison) que je devrais plutot utiliser toUnicode au lieu de fromUnicode. Ainsi j'ai utilisé le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QTextCodec *codec = QTextCodec::codecForName("ISO 8859-15");
    reponseReq  = (codec->toUnicode(maQuery->value(x).toByteArray()));
    Mais cela ne fonctionne pas egalement


    Par contre en mode debug, les resultat retourné par maQuery->value(x) est toujours '/17775'. Avec l'aide d'une autre personne, on a découvert grace à google que:
    FFFD REPLACEMENT CHARACTER
    * used to replace an incoming character whose value is unknown or unrepresentable in Unicode
    * compare the use of 001A as a control character to indicate the substitute function
    U+FFFD, character �‬, decimal 65533, hex 0xFFFD, octal \177775, binary 1111111111111101
    UTF-8: 0xf0 0x8f 0xbf 0xbd
    Donc je suppose que le probleme est en amont...

    Cette personne m'a egalement proposé de vérifier:
    http://qt.developpez.com/doc/4.7/sql-driver/
    Section "ODBC Unicode Support"
    Q_ODBC_VERSION_2 ou not Q_ODBC_VERSION_2
    mais la j'en sais rien et je ne trouve pas la réponse mais comme ma base n'est pas en unicode je pense que cela n'a rien a voir mais bon je me mélange un peu les pinceaux...

    Enfin le driver que j'utilise est bien le bon ? "SQL SERVER NATIVE CLIENT 10.0" pour un "sql server 2008R2" ?

    merci encore de vos réponses ...

  6. #6
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonsoir,

    Je ne sais pas si cela peut ou non améliorer les choses, mais les lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    Devraient probablement être changées par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("ISO 8859-15"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("ISO 8859-15"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("ISO 8859-15"));
    Les sources peuvent également être réencodées en ISO-8859-15, ce qui permettra d'appeler maQuery->value(x).toString() sans autre élément et d’interpréter correctement les données. Ou du moins, dans la théorie. Il y a également la piste de fromRawData() par rapport au résultat de la requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    reponseReq = QString(QByteArray::fromRawData(qPrintable(maQuery->value(x).toString()), maQuery->value(x).toString().size()));
    Concernant le support de l'Unicode, je n'aime pas beaucoup le résultat (false), mais je ne saurais pas dire ce que ça change. Le fait d'éplucher cette page pourrait s'avérer utile (ils parlent d'UTF-16, à voir ce que ça implique).

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    merci de votre réponse, j'ai commencé à étudier tout ca, mais maintenant ca attendra lundi pour le reste.
    bon week end !!



    edit: en lisant la doc je me suis rendu compte que j'utilisais pas au bon endroit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     qDebug() << "code la base" << maDb.driver()->hasFeature(QSqlDriver::Unicode);
    et en fait le resultat n'est pas false...

  8. #8
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    C'est une information quelque peu rassurante. Bon week-end à vous, dans ce cas.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Ce problème devant maintenant être absolument résolu je me suis replongé dedans. Après (encore) plusieurs jours de recherche j'ai enfin trouvé !

    Et comme j'ai tellement galéré et perdu de temps que je viens partager la solution (malgré les 3 ans qui sépare ce jour de la date de mon 1er post). Vous allez voir, ca ressemble presque plus à un bug qu'autre chose !

    En fait il suffit avant de préparer sa requête de faire un simple "clear()":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    maQuery.clear() ;
     
    maQuery.prepare(...) ;


    C'est tout ! oui ! oui !

    Au final cela fonctionne parfaitement et cela fait franchement plaisir !

    En espérant que cela vous sera utile !

  10. #10
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 2
    Points : 3
    Points
    3
    Par défaut thanks mate you saved me so much headache

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Script shell pour enlever les caractères spéciaux d'un nom de fichier
    Par babo dans le forum Shell et commandes GNU
    Réponses: 9
    Dernier message: 12/09/2008, 13h49
  2. Réponses: 1
    Dernier message: 13/02/2007, 16h53
  3. Réponses: 8
    Dernier message: 13/12/2006, 18h17
  4. [Applet][XML] Ne pas interpréter les caractères spéciaux
    Par leminipouce dans le forum Format d'échange (XML, JSON...)
    Réponses: 4
    Dernier message: 28/07/2005, 16h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo