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

Format d'échange (XML, JSON...) Java Discussion :

Conversion ISO8859-15 en UTF8


Sujet :

Format d'échange (XML, JSON...) Java

  1. #1
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 56
    Par défaut Conversion ISO8859-15 en UTF8
    Bonjour,

    J'extrait via une connexion JDBC un champ CLOB dans l'encoding ISO8859-15 pour convertir et générer un fichier XML dans l'encoding UTF8 à partir d'un traitement JAVA.

    Le problème est le suivant : les majuscules accentuées ne sont pas correctement convertis : des carrés à la place.

    Tous les autres accents sortent bien.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Ce n'est pas un problème d'encodage mais un problème de fonte si t'as des carrés à l'affiche. Vérifie les octes dans le fichier en question et je suis certain qu'ils doivent être corrects.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par edwin301 Voir le message
    Le problème est le suivant : les majuscules accentuées ne sont pas correctement convertis : des carrés à la place.

    Tous les autres accents sortent bien.
    Dans ce cas, c'est dans la BDD que les majuscules accentuées sont incorrectes. Elles ont été mal enregistrées, il n'y a plus rien à y faire.

    Ou alors, tu fais un traitement bizarre et inutile entre BDD et XML.

    Edit : Ah, ce que dit tchize est fort possible, en effet.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    La réponse de thelvin est aussi probable. Un CLOB ce n'est pas un BLOB, c'est soumis aux règles d'encodage de la DB. D'ailleurs, avec un CLOB, normalement, tu n'a pas à connaitre "l'encodage", tu récupère un Reader directement via Clob.getCharacterStream()

  5. #5
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 56
    Par défaut
    Il ne s'agit pas seulement de l'affichage mais dans le fichier, j'ai bien des carrés pour le caractère 'É', alors que en BDD j'ai 'Ã?'.

    La bdd est en character set iso 8859 et le fichier de sortie en UTF8.
    La conversion iso8859-15 en utf8 ne fonctionne pas et ceci uniquement pour les majuscules accentuées.

    Pour un CLOB tu n'as pas à connaitre l'encodage oui, mais quand tu veux un format de sortie différent (impératif), il faut savoir l'encoding d'entrée et de sortie :
    new String(maChaine.getBytes("ISO8859-15"), "UTF8").
    Sans faire cela, tous les accents (majuscule et miniscule) sortent avec des caractères étranges.

    Un conseil sans bidouiller ?

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par edwin301 Voir le message
    new String(maChaine.getBytes("ISO8859-15"), "UTF8").
    Si tu fait cela c'est normal que tu n'obtiennes rien de bien !!!
    Tu converties une chaine en byte encodé en ISO8859-15, que tu re-transformes en chaine en décodant de l'UTF-8.



    Une chaine n'est pas associé à un encodage : en mémoire les chars sont encodés en UTF-16 !

    Tu ne dois spécifier l'encodage que lorsque tu lis ou écris un flux binaire.



    Bref supprimes cette ligne de code et ca devrait marcher bien mieux... s'il n'y a pas d'autres atrocité de ce genre.



    a++

  7. #7
    Membre très actif Avatar de unknow0
    Homme Profil pro
    Inscrit en
    Juillet 2008
    Messages
    452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 452
    Par défaut
    Citation Envoyé par edwin301 Voir le message
    new String(maChaine.getBytes("ISO8859-15"), "UTF8").
    si ne me m'abuse c'est sa le problème, la se que tu fait c'est décoder de l'iso comme si c'était de UTF8.
    la ou tu doit spécifier UTF8 c'est au moment d'écrire ton fichier de sortie.

    EDIT: grilé en mieu en plus xD

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    CA:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new String(maChaine.getBytes("ISO8859-15"), "UTF8").
    Ca ne fait CERTAINEMENT pas une conversion, ça fait une soupe!

    Tu prend ta chaine, tu la "sauve" (byte[]) en ISO8859-15 et puis tu lui dit de la relire en disant "ha mais tout compte fait, non j'ai stocké de l'UTF-8", ca n'a pas de sens.

    Pour sauver en UTF-8, on crée un Writer avec de l'utf-8, et tu fais un write(laString) avec ça. Et tu n'a pas besoin de l'encodage d'origine:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Reader r = clob.getReader();
    OutputStream outputStreamFichier = new FileOutputStream(....);
    Writer w = new OutputStreamWriter(outputStreamFichier,"UTF-8"));
    char[] buffer = new char[2048];
    int read = 0;
    while ( (read=r.read(buffer)) > 0)
       w.write(buffer,0,read);
    + nettoyage / flush / fermeture etc

  9. #9
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 56
    Par défaut
    Je vois qu'y a de la bonne volonté.
    Cependant si j'ai ajouté cette conversion c'est parceque le simple fait d'utiliser un writer avec l'encoding UTF-8
    Writer w = new OutputStreamWriter(outputStreamFichier,"UTF-8"))

    ne suffit pas pour traiter correctement les accents en minuscule.

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    tu les lit comment de la DB tes données? A priori, ça semble indiquer que les données sont stockée de travers dans la base de données. LA soupe que tu fais est une soupe corrective a posteriori, mais il y a toujours des pertes.

  11. #11
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 56
    Par défaut
    Une requête via connexion JDBC permet d'extraire le CLOB.
    Puis utilisation d'un reader pour stocker le CLOB dans un StringBuffer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BufferedReader clobReader = new BufferedReader(clob.getCharacterStream());

  12. #12
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Dans ce cas, si ce n'est pas bon a la sortie du bufferedReader, c'est vraisemblablement qu'on a stocké n'importe quoi dans la DB. C'est stocké comment dans la DB. Le processus qui y écrit est-il correct?

  13. #13
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Un peu plus de code serait le bienvenue, surtout s'il y a d'autres surprises comme cela....


    Ensuite s'il s'agit d'une appli Desktop tu peux utiliser JOptionPane.showMessage() pour vérifier que ta chaine soit correctement encodé une fois récupéré depuis la BD.


    Sinon comment tu vérifies l'encodage du fichier final ?


    a++

  14. #14
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ce qui revient à ce qu'on a déjà dit : si ça se trouve les données sont mal enregistrées dans la BDD. Ce n'est pas avec la bouillie que tu nous as montrée qu'on va pouvoir savoir si c'est le cas ou non. Si tu peux trouver un moyen de lire correctement ce CLOB, avec n'importe quel outil de BDD, dans ce cas, les données y sont peut-être correctes. Sinon, non.

    Autre possibilité : le driver JDBC se trompe en détectant automatiquement le charset employé pour transmettre ce CLOB, et résultat tu lis des données erronées. Auquel cas, il va peut-être falloir regarder dans la configuration de ce driver, comment imposer un charset. Ou quelque chose comme ça.

    Dans tous les cas, XML n'a rien à voir là-dedans, et les traitements à base de getBytes() ont peu de chance de pouvoir réparer quoi que ce soit (par contre ils peuvent très facilement casser des choses.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 56
    Par défaut
    Je ne connais pas exactement le process qui a été utilisé pour charger les données en base.

    En terme de code, pour écrire ensuite dans le fichier c'est la ligne suivante qui est réalisée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Writer fos =  new BufferedWriter(new OutputStreamWriter(
    				        new FileOutputStream(f, true), "UTF-8"));
    fos.write(xml);
    xml étant la chaîne à écrire.

    Voici ce que j'ai en base dans le CLOB pour le mot Activités par exemple : Activités (en ISO-8859-15).
    Dans le fichier en sortie j'ai Activités grâce à la fameuse ligne String(maChaine.getBytes("ISO8859-15"), "UTF8"), sinon ça reste Activités.

    Je précise que si je génère un fichier ISO, à ce moment-là le mot Activités apparaît bien sans faire la transformation de la chaîne, idem pour les majuscules accentuées.
    Le problème est que c'est un charset UTF8 qui est attendu ce qui pose problème uniquement pour les majuscules accentuées, pour rappel.

  16. #16
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par edwin301 Voir le message
    Voici ce que j'ai en base dans le CLOB pour le mot Activités par exemple : Activités (en ISO-8859-15).
    Donc soit les données sont mal encodé dans la base de données, et il serait préférable de corriger cela.
    Soit c'est le driver JDBC qui est mal configuré et qui lit mal les données...

    Dans les deux cas la solution est en amont et pas dans le code.

    Citation Envoyé par edwin301 Voir le message
    Dans le fichier en sortie j'ai Activités grâce à la fameuse ligne String(maChaine.getBytes("ISO8859-15"), "UTF8"), sinon ça reste Activités.
    Comme on l'a dit ce genre de code est une hérésie.
    Si ca semble marcher pour certains caractères c'est justement parce que la lecture de "maChaine" est incorrecte. Mais c'est du bidouillage qui tombe en "marche"...

    a++

  17. #17
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par edwin301 Voir le message
    Voici ce que j'ai en base dans le CLOB pour le mot Activités par exemple : Activités (en ISO-8859-15).
    Donc les données dans le CLOB sont a priori déjà corrompues. Essayer de rattraper la soupe avec la bouillasse qu'il y a dedans est compliqué.
    Un chose me chifonne, d'où tire-tu la conclusion que le CLOB est en ISO-8859-15? Quel base de données (oracle, mysql, ....)


    Pour résumer les chose, créer et récupérer les données vers un CLOB, les opérations suivante devraient avoir été effectuées:


    fichier(au format encodage 1) -> lecture avec un reader (avec encodage 1) -> String java -> envoie par le driver JDBC (encodage 2) -> décodage par serveur DB (encodage 2) et stockage dans le serveur (encodage 3) -> lecture par le serveur (encodage 3) -> envoi vers java (encodage 4) -> décodage par le driver (encodage 4) -> String -> envoi vers un writer (encodage 5).

    La partie en bleu ne devrais pas te concerner.

    Quand les encodages ont le mêmes chiffres, il doivent être les même car il s'agit de points où l'on transfère du binaire. Encodage 2 a peu de chances d'être inccorect. En général le serveur est capable de se dépatouiller. De mon expérience, 60% des erreurs sur encodage 1 (le fichier sur disque est en UTF-8, on le lit avec un reader ISO-8859-1 par exemple), 30% des erreurs dans le choix encodage 5 (on écrit en utf-8 alors que le client veux de l'iso) et 10% des erreur dans la configuration du driver JDBC (le serveur pense qu'on travaille sur la connexion en XYZ et en fait on est en ABC). Mais dans ce dernier cas, les varchars aussi sont corrompus!

    A noter que si on fait cette erreur:

    fichier(utf-8) -> lecture avec un reader (iso-8859-1) -> String java -> envoie par le driver JDBC (encodage 2) -> décodage par serveur DB (encodage 2) et stockage dans le serveur (encodage 3) -> lecture par le serveur (encodage 3) -> envoi vers java (encodage 4) -> décodage par le driver (encodage 4) -> String -> envoi vers un writer (iso-8859-1).

    on peux avoir l'impression que tout est correct car au final on réécrit avec un writer inverse du reader d'origine, et on obtiens un fichier final en utf-8. Mais malheurseument, ça foire sur des cas borderline: certains caractère précis en utf-8 qui, lut avec un filtre iso donnent des caractères osbcont dans le language chinois qui ne peuvent pas être stockés dans la base de données, ou des surrogates qui sont simplifiées par java

  18. #18
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par edwin301 Voir le message
    Activités (en ISO-8859-15).
    ça ne peut pas être de l'ISO-8859-15, il est codé sur 8bits.
    ça ressemble plus à de l'UTF-8.
    ce qui tend à confirmer que les données sont déjà corrompues dans la DB ou qu'elles sont codées en UTF.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  19. #19
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    ça ne peut pas être de l'ISO-8859-15, il est codé sur 8bits.
    ça ressemble plus à de l'UTF-8.
    Ni l'un ni l'autre c'est de l'utf-8-vu-en-iso, bref, c'est des caractère, déterminer un encodage nécessite qu'on aie les octets, pas les caractères

  20. #20
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Sauf qu'en l'occurrence, é est la représentation de é UTF-8 en ISO-8859-1.
    Donc, pour moi, à la base c'est de l'UTF-8
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. fonction de conversion de caracteres en utf8
    Par renkev dans le forum Langage
    Réponses: 12
    Dernier message: 14/04/2011, 12h13
  2. absence de conversion de locale vers utf8 dans un code
    Par minibus dans le forum GTK+ avec C & C++
    Réponses: 8
    Dernier message: 12/08/2009, 11h32
  3. conversion UTF8 vers ASCII en C
    Par znarf dans le forum C
    Réponses: 2
    Dernier message: 05/07/2006, 13h55
  4. prob de Conversion carac spéciaux en UTF8: PERL 5.6.1
    Par kaizersozer dans le forum Modules
    Réponses: 2
    Dernier message: 24/02/2006, 19h02
  5. [i18n][utf8] Outils pour convertir iso8859-1 en unicode/utf8
    Par co2 dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 07/11/2005, 09h56

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