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

Langage PHP Discussion :

Export CSV - Encodage de caractère


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut Export CSV - Encodage de caractère
    Bonjour à tous,

    Toujours dans le sujet de mon export CSV résolu dans mon post précédent.
    J'ai un soucis d'encodage de caractère et je ne sais pas comment le résoudre.

    La base de données à été à mon sens polluée lors de précédent export/import (avant mon arrivée), et je me retrouve avec des caractères de type : é, ê, etc...
    un utf8_encode ou utf8_decode ne fait qu’aggraver la chose. Et si je ne dit pas de bêtise utf8_decode à été rendu obsolète en PHP8 version dans laquelle je suis.
    pareil, preg_replace ou str_replace ne fonctionne pas du moins pas la manière dont je le fait sûrement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    preg_replace("é","é",$str); // Résultat inchangé
    str_replace("é","é",$str);   // Résultat inchangé
    Donc j'ai des noms qui sont déformé à cause de cela et qui empêche l'importation, même la recherche simple (ce qui à causé beaucoup de doublons).

    Exemple

    Un client est bien encodée : Frédérique tartempion
    Mais un suivant par contre : Fédérique tartempion

    Le tout dans la même base de données, je suppose que lors des précédents export/import, le personnel en charge de la chose n'a pas fait attention à l'encodage de caractères avant, ce qui forcément me place dans une situation plus que compliqué.
    La direction veux que ces problème de caractère soit régler avant d'importer (ce que je peux comprendre).
    Le faire manuellement serait bien trop lourds car cela touche près de 120.000 Clients sur 210.000 (soit plus de la moitié).

    Et du coup c'est pareil dans mon CSV, des clients on bien leurs accents mais pas d'autres.

    Ma question est donc : comment puis-je résoudre cette problématique ?
    Le faire manuellement est très lourd.

    Je suis ouvert à toutes les possibilités mais l'idéal serait de pouvoir convertir tous les caractères qui pose problème c'est à dire, les caractère accentué tel que : é, ê, etc... en vrai caractère é, è, etc...

    D'avance merci de l'aide qui vous pourriez m'apporter.
    Belle journée à vous
    Spliffer

  2. #2
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 369
    Points : 5 734
    Points
    5 734
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    peut-être utiliser les expressions régulières...
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  3. #3
    Membre averti Avatar de ddaweb
    Homme Profil pro
    Webmaster amateur
    Inscrit en
    Janvier 2013
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Webmaster amateur
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Janvier 2013
    Messages : 329
    Points : 430
    Points
    430
    Par défaut
    Je crois que ceci pourrait faire l'affaire : https://www.php.net/manual/fr/functi...t-encoding.php

    Je viens de me rendre compte que la fonction utf8_decode est déprécié en PHP 8.2
    Ce poste m'a permis de pouvoir faire évoluer mon script, également utilisé pour la création d'un CSV.
    Je vais tester cette nouvelle fonction.

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    Merci pour vos réponse.

    Pour les expression régulière peut-être bien, mais je ne suis pas du tout familier avec (il serait temps de m'y mettre je sais, mais niveau dispo c'est cours lol)

    Pour la fonction : mb_detect_encoding
    Je suis justement penché dessus

    Alors là j'arrive dans une problématique encore plus énervant je vous explique :

    Ma BDD MySQL est en InnoDB et en utf8_general_ci
    Mes fichier sont encodé en utf8
    Le charset HTML (utilisé pour les formulaire) est bien sur utf-8
    Donc là tout est sensé être en utf8

    et bien non

    Voici ma logique.
    Faire une requête sur 5 enregistrement (en effet les problèmes arrive dès la 5ème ligne de la table)
    pour chaque ligne :
    - Affiche l'encodage actuel pour chaque colonne avec mb_detect_encoding
    et là le résultat est encore plus surprenant car je me retrouve avec :
    - Mes lignes sans problème détecte un encodage ASCII
    - Les lignes posant problème détecte un UTF-8
    Ce qui est plutôt étrange, pourquoi mais données correcte affiche un ASCII alors que tout est fait pour de l'UTF-8 ? comprends pas

    Bref dans ce contexte, je me dit "ok, puisque les lignes posant problème sont en UTF8 je vais les convertir en ASCII" oui mais ASCII ne fonctionne pas et en réalité j'ai dû mettre en "iso-8859-1" qui apprès conversion me détecte alors un ASCII.
    Et là magie avec un encoding en "iso-8859-1" tout est ok ouf, "on va vérifier quand-même sur une sélection un peu plus grand pour être sûr", et là beurk.

    A certain moment, il me détecte une chaîne en utf8 mais là mes é et autres caractères accentués se transforme en �
    Je ne comprend plus rien.

    En vrai cette base de données est à mon sens un vrai foutoir sans nom.
    Je me retrouve avec :
    - des clients qui on un nom encodé en utf8 et un prénom en ASCII (allez savoir pourquoi)
    - des clients avec des adresses qui on une commune encodée en ASCII et une rue en utf8 ou inversément

    Plus j'avance dans la chose et plus je suis horrifié et un peu venèr de me retrouver avec ça sur le dos.

    Donc je continue de poursuivre mes recherche afin de trouvé quelques chose qui puise me régler cela.

    Belle journée à vous
    Spliffer

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    une ébauche de solution :

    1 : par expression régulière modifié tous les é et autre directement avec le bon caractère accentué, j'ai donc relevé les différent caractère qui pose soucis jusqu'a présent
    2 : une fois la conversion effectué, passer tous les encodage ASCII en UTF8

    Ce qui devrait me donner une bdd propre si ma logique est bonne
    le point 2 pas de soucis, mais le point 1 c'est autre chose et à tout les coup c'est parce que je m'y prend mal.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php 
    function preg($str){
        $search = array('/é/','/ê/','/ÃÂ/','/ç/','/A“/','/â/','/î/','/ÃÂ/');
        $replace = array('é','ë','è','ç','oe','â','î','à');
        return preg_replace($search, $replace, $str);
    }
     
    // $r['nom'] est le retour dans ma requête
    $nom = preg($r['nom']);
     
    ?>
    et Frédérique devient => Frédérique
    Donc je dois mal m'y prendre, je creuse la question, mais c'est ce qui me semble le plus correcte à faire histoire d’harmoniser une bonne fois la base de données.

    Belle journée à vous
    Spliffer

  6. #6
    Membre averti Avatar de ddaweb
    Homme Profil pro
    Webmaster amateur
    Inscrit en
    Janvier 2013
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Webmaster amateur
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Janvier 2013
    Messages : 329
    Points : 430
    Points
    430
    Par défaut
    Je penses vraiment qu'il n'y a pas besoin de tout cela, je ne fais rien du genre et tout fonctionne.
    Je n'ai pas encore eu de temps de modifier mon code déprécié pour me prononcer à 100%.

    Dans le <head>, je mets un méta :
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  7. #7
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 369
    Points : 5 734
    Points
    5 734
    Billets dans le blog
    1
    Par défaut
    Je viens de tester ta fonction, et moi j'ai Frédérique qui donne Frédérique alors
    Il vaut mieux viser la perfection et la manquer que viser l'imperfection et l'atteindre. - Bertrand Russell

    Si la discussion est résolue, merci de cliquer sur le bouton

  8. #8
    Membre averti Avatar de ddaweb
    Homme Profil pro
    Webmaster amateur
    Inscrit en
    Janvier 2013
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Webmaster amateur
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Janvier 2013
    Messages : 329
    Points : 430
    Points
    430
    Par défaut
    Je viens de tester et cela fonctionne, voici la différence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $liste_code_compta='Récapitulatif code compta : '.$texte_cours_mois.' '.$cours_annee_select;
    //$liste_code_compta_csv=utf8_decode($liste_code_compta);   // ----- Avant PHP 8.2
    $liste_code_compta_csv = mb_convert_encoding($liste_code_compta, "ISO-8859-1", "UTF-8");   // ----- >= PHP 8.2
    $array_titre=[$liste_code_compta_csv,$cours_annee_select];
    $array_entetes=['Code compta', 'Nom', 'Somme','TVA'];
    // ---------- Création CSV
    if(file_exists($fichier)) { 						// ----- Supprimer le fichier s'il esiste
    	unlink($fichier); 
    }
    $csv = fopen($fichier, "w");						// ----- Crée le fichier
    fputcsv($csv,$array_titre,';');					        // ----- Période concernée
    fputcsv($csv,$array_entetes,';');					// ----- Entête des colonnes
    ...
    Cela donne ceci avec Excel pour la liste des codes compta de ma BDD (UTF-8) : il me reste à diminuer mon code

    Nom : excel2.jpeg
Affichages : 58
Taille : 42,5 Ko

    Toute mes pages PHP sont également en UTF-8 !

    Nom : encodage.jpeg
Affichages : 57
Taille : 15,5 Ko

  9. #9
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Pour aborder ce genre de problème:
    • Vérifier que tout est bien configuré en UTF-8 (y compris la base de données, la connection à la base de données via PHP, l'éditeur de code).
    • Armé de liens vers la table UNICODE avec son encodage en UTF-8 et les jeux de caractères les plus fréquents pour le français (ISO-8859-1, ISO-8859-15, Windows-1252), ainsi que d'une fonction pour afficher les octets d'une chaîne, essayer de retracer le scénario qui a conduit au problème. Exemple:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      function displayBytes($str) {
          for ($i=0; $i<strlen($str); $i++) {
              echo strtoupper(dechex(ord($str[$i]))), ' ';
          }
      }
       
      displayBytes('é'); // C3 83 C6 92 C3 82 C2 A9
      Cette fonction est trés importante car en te montrant les octets, tu pourras déterminer de façon irréfutable s'il s'agit d'UTF-8 ou non.


      Ce qui donne (chez moi):
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // Ã       ƒ       Â       ©
      // C3 83   C6 92   C3 82   C2 A9  <-- UTF-8 (état actuel)
      // C3      83      C2      A9     <-- Windows-1252
       
      // Ã       ©
      // C3 83   C2 A9  <-- UTF-8
      // C3      A9     <-- Windows-1252
       
      // é
      // C3 A9  <-- UTF-8 (état initial)
      Dans ce scénario plutôt plausible, par deux fois la chaîne encodée en UTF-8 a été interprétée comme si elle utilisait le jeu de caractères Windows-1252 puis réencodée en UTF-8.
    • Si tu arrives à isoler les parties de la base de données incriminées (à l'aide d'indices comme une date d'enregistrement, ou l'utilisateur qui a saisi les données), tu peux tenter la (double) conversion inverse:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      echo mb_convert_encoding(mb_convert_encoding('é', 'Windows-1252', 'UTF-8'), 'Windows-1252', 'UTF-8');
      L'avantage c'est que tu n'as pas besoin de rechercher un caractère en particulier.
    • Par contre si c'est un joyeux mélange et qu'il faut tout passer en revue, alors oui dans ce cas autant faire des remplacements de chaîne. Mais pas besoin de regex pour ça puisque tu veux remplacer des chaînes fixes, strtr (avec la signature alternative: tableau associatif en 2e paramètre) fera très bien l'affaire.


    En vrac:
    • Fait des essais sur un copie de la table.
    • Un e dans l'o, ce n'est pas un o suivi d'un e mais bien le caractère œ.
    • "Convertir en ASCII" ne veut rien dire, la plage ASCII (les caractères de 00 à 1F) est commune à la plupart des jeux de caractères ainsi qu'à l'encodage UTF-8, et elle ne concerne pas les caractères accentués (à la limite on peut faire une translitération d'un jeu de caractère vers l'ASCII, ce qui remplacera les caractères accentués par leurs équivalents non accentués de la plage ASCII).
    • Ne place pas trop d'espoirs dans la fonction mb_detect_encoding qui ne peut pas faire la différence entre deux jeux de caractères codés sur un octet (et pour cause c'est impossible la plupart du temps).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  10. #10
    Membre régulier
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Points : 114
    Points
    114
    Par défaut
    Bonjour à tous,

    Tout d'abord merci pour votre participation.

    La fonction fonctionne en effet, met mon problème comme je le disait, c'est que j'ai 2 jeux de caractères différents dans ma table.
    Et en utf-8 certains caractères accentués passe correctement mais les autres m'affiche les caractères tronqués. ce qui signifie soit un double encodage soit importé comme tel sans vérification.

    Donc le problème est résolu, en utilisant un bidouillage peut-être mais fonctionnel sur ma base de données (ou du moins sur les données de ma base de données, pour laquelle plusieurs import on été fait sans prendre en compte le jeux de caractères)

    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
    // A amélioré encore sûrement
    function checkChar($str){
        // Si la chaîne est détectée en UTF-8
        if(mb_detect_encoding($str) == 'UTF-8'){
            // On s'occupe d'abord du cas ou des accents sont présent mais bien encodé
            // Cela pour éviter le double encodage, alors qu'il est déjà bon, ce qui génrerai des ? dans un losange
            $search_ex = array('/é/','/ë/','/è/','/ç/','/oe/','/â/','/î/','/à/');
            $search = array('é','ë','è','ç','oe','â','î','à');
            $replace_ex = array('/\[ET\]/','/\[EY\]/','/\[ES\]/','/\[CS\]/','/\[OE\]/','/\[AC\]/','/\[IC\]/','/\[AA\]/');
            $replace = array('[ET]','[EY]','[ES]','[CS]','[OE]','[AC]','[IC]','[AA]');
            $str = preg_replace($search_ex, $replace, $str);
            // Maintenant on converti la chaîne, pour la rendre compatible avec toutes les données
            $str = mb_convert_encoding($str, 'iso-8859-1');
            // Mes é sont devenu des é, etc...
            // on peux donc replacé les caractères qui étaient bon
            $str = preg_replace($replace_ex, $search, $str);
        }
        return $str;
        // Je peux faire le ré-encodage en UTF8 à la sortie si besoin
        // return utf8_encode($str); 
    }
    Ceci me permet de corrigé les problèmes actuel, et je peux ensuite tout passer en utf-8 sans avoir de soucis, et j'ai enfin obtenu une table uniquement en utf-8 et tous mes caractères accentués sont bons

    Merci à tous pour vos contributions
    Belle journée à tous.

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

Discussions similaires

  1. [AC-2007] Problème export csv limité à 255 caractères !
    Par podalamina dans le forum Access
    Réponses: 15
    Dernier message: 15/10/2012, 16h03
  2. [XL-2003] Export *.CSV avec nombre de caractère fixe par ligne
    Par IronBibs dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 04/09/2011, 02h55
  3. [CSV] Export CSV valeurs/chaine de caractères
    Par Nemesis007 dans le forum Langage
    Réponses: 2
    Dernier message: 14/05/2008, 13h53
  4. Réponses: 4
    Dernier message: 29/02/2008, 11h11
  5. Export au format CSV limité à 255 caractères
    Par RKU01 dans le forum Access
    Réponses: 1
    Dernier message: 07/12/2006, 04h53

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