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

PHP & Base de données Discussion :

array_multisort et encodage du fichier


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2016
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2016
    Messages : 109
    Par défaut array_multisort et encodage du fichier
    Bonjour,

    Je fais des tests avec le même site sur différents serveurs et les résultats obtenus m'étonnent.

    Contexte : Dév PHP avec base de données MySQL (exemples : http://aleph2at.free.fr ou http://www.aleph2at.fr)

    Je fais des tests sur 3 serveurs :
    - free.fr
    Base de données MySQL et tables en UTF8 version 5.3.x de PHP
    - alwaysdata
    Base de données MySQL et tables en UTF8 version 7.2.x de PHP
    -localhost
    Base de données MySQL et tables en UTF8 version 7.2.x de PHP

    Tous les php des 3 serveurs sont issus d'une même source (mon workspace sous eclipse) en UTF8 sauf un fichier encodé en ANSI pour les serveurs Free.fr et localhost :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    <?php
     
    function sans_accents($string)
    // Retoune une chaine de caractère sans les accents
    {
        $translit = array(
            'Á' => 'A',
            'À' => 'A',
            'Â' => 'A',
            'Ä' => 'A',
            'Ã' => 'A',
            'Å' => 'A',
            'Ç' => 'C',
            'É' => 'E',
            'È' => 'E',
            'Ê' => 'E',
            'Ë' => 'E',
            'Í' => 'I',
            'Ï' => 'I',
            'Î' => 'I',
            'Ì' => 'I',
            'Ñ' => 'N',
            'Ó' => 'O',
            'Ò' => 'O',
            'Ô' => 'O',
            'Ö' => 'O',
            'Õ' => 'O',
            'Ú' => 'U',
            'Ù' => 'U',
            'Û' => 'U',
            'Ü' => 'U',
            'Ý' => 'Y',
            'á' => 'a',
            'à' => 'a',
            'â' => 'a',
            'ä' => 'a',
            'ã' => 'a',
            'å' => 'a',
            'ç' => 'c',
            'é' => 'e',
            'è' => 'e',
            'ê' => 'e',
            'ë' => 'e',
            'í' => 'i',
            'ì' => 'i',
            'î' => 'i',
            'ï' => 'i',
            'ñ' => 'n',
            'ó' => 'o',
            'ò' => 'o',
            'ô' => 'o',
            'ö' => 'o',
            'õ' => 'o',
            'ú' => 'u',
            'ù' => 'u',
            'û' => 'u',
            'ü' => 'u',
            'ý' => 'y',
            'ÿ' => 'y'
        );
        $string = strtr($string, $translit);
        return preg_replace('#[^a-zA-Z0-9\-\._]#', ' ', $string);
    }
     
    ?>
    donc si ce fichier PHP est en ANSI sur free.fr et localhost, le tri se fait correctement et si ce fichier PHP est en UTF8 sur alwaysdata, le tri se fait correctement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        foreach ($return2 as $key => $row) 
        // On mappe la clé Nom2 pour le tri multiple
        {
            $El_Nom[$key] = strtolower($row['Nom2']);
        }
      $El_Nom_sans_accent = array_map('sans_accents', $El_Nom); // On enlève les accents sur le tableau $El_Nom qui contient les noms avec accents
        array_multisort($El_Nom_sans_accent, SORT_ASC, SORT_STRING, $return2); // On fait le tri multiple en appliquant le tri d'El_Nom_sans_accent à $return2 qui contient la liste avec accent
    Si je passe le fichier de la fonction sans_accents en UTF8 sur localhost ou free.Fr, le tri est incorrect.
    Si je passe le fichier de la fonction sans_accents en ANSI sur alwaysdata, le tri est incorrect.

    Je pense que la solution est toute bête mais pour l'instant je ne la vois pas.

    Une idée ?

  2. #2
    Membre Expert
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Par défaut
    Des exemples avant après ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2016
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2016
    Messages : 109
    Par défaut
    Citation Envoyé par badaze Voir le message
    Des exemples avant après ?
    Voici plusieurs fichiers :
    - Liste_avec_accent_avant_tri.txt
    La liste de base commune avant tri
    - Cas ANSI :
    sur ce serveur (localhost) c'est OK quand le fichier est en ANSI
    + Liste_sans_accent_après_tri_ANSIOK.txt
    Liste triée sans accent
    + Liste_avec_accent_après_array_map_ANSI_OK.txt
    Liste triée avec accent après le array_map
    - Cas UTF8 :
    sur ce serveur c'est KO quand le fichier est en UTF8
    + Liste_sans_accent_après_tri_UTFK.txt
    Liste triée sans accent
    + Liste_avec_accent_après_array_map_UTF8_OK.txt
    Liste triée avec accent après le array_map

    Il semble que le traitement "sans_accent" fait sauter les caractères accentués dans le cas UTF8.
    Fichiers attachés Fichiers attachés

  4. #4
    Membre Expert
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Par défaut
    Peut-être qu'en passant par un tri insensible au type d'encodage cela fonctionnera dans tous les cas. Dans l'exemple qui suit je convertis les caractères en valeurs ASCII hexadécimale.
    Par contre je ne sais pas si la fonction ord fonctionne de la même manière en UTF-8 et en ANSI ?!?

    Code php : 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    <?php
    function sans_accents($string)
    // Retourne une chaine de caractère sans les accents
    {
        $translit = array(
            'Á' => 'A',
            'À' => 'A',
            'Â' => 'A',
            'Ä' => 'A',
            'Ã' => 'A',
            'Å' => 'A',
            'Ç' => 'C',
            'É' => 'E',
            'È' => 'E',
            'Ê' => 'E',
            'Ë' => 'E',
            'Í' => 'I',
            'Ï' => 'I',
            'Î' => 'I',
            'Ì' => 'I',
            'Ñ' => 'N',
            'Ó' => 'O',
            'Ò' => 'O',
            'Ô' => 'O',
            'Ö' => 'O',
            'Õ' => 'O',
            'Ú' => 'U',
            'Ù' => 'U',
            'Û' => 'U',
            'Ü' => 'U',
            'Ý' => 'Y',
            'á' => 'a',
            'à' => 'a',
            'â' => 'a',
            'ä' => 'a',
            'ã' => 'a',
            'å' => 'a',
            'ç' => 'c',
            'é' => 'e',
            'è' => 'e',
            'ê' => 'e',
            'ë' => 'e',
            'í' => 'i',
            'ì' => 'i',
            'î' => 'i',
            'ï' => 'i',
            'ñ' => 'n',
            'ó' => 'o',
            'ò' => 'o',
            'ô' => 'o',
            'ö' => 'o',
            'õ' => 'o',
            'ú' => 'u',
            'ù' => 'u',
            'û' => 'u',
            'ü' => 'u',
            'ý' => 'y',
            'ÿ' => 'y'
        );
        $string = strtr($string, $translit);
        return preg_replace('#[^a-zA-Z0-9\-\._]#', ' ', $string);
    }function toHEX($string)
    {
     $return = "";
     for ($i=0;$i<strlen($string);$i++)
     {
      $return = $return.dechex(ord(substr($string,$i,1)));
     }
     
     return $return;
    }
     
    $return2 = file('Liste_avec_accent_avant_tri.txt');
    foreach ($return2 as $key => $row) 
    {
        $El_Nom[$key] = toHEX(sans_accents(strtolower($row)));
    }
    array_multisort($El_Nom, SORT_ASC, SORT_STRING, $return2); 
     
    foreach($return2 as $value)
    {
     print "$value<br/>";
    }
    Fichiers attachés Fichiers attachés

  5. #5
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    les fonctions strtr() et strtolower() ne sont pas compatibles UTF-8, elles pètent les chaînes de caractères.
    Pour les fichiers encodés UTF-8, tu dois utiliser str_replace et mb_strtolower.
    D'ailleurs, tu ne dois plus t'embêter : tu encodes tout en UTF-8 sans BOM et utilises uniquement la bibliothèque unicode (fonctions mb_xxx, multibyte strings)

  6. #6
    Membre confirmé
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2016
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Santé

    Informations forums :
    Inscription : Décembre 2016
    Messages : 109
    Par défaut
    Citation Envoyé par rawsrc Voir le message
    Salut,

    les fonctions strtr() et strtolower() ne sont pas compatibles UTF-8, elles pètent les chaînes de caractères.
    Pour les fichiers encodés UTF-8, tu dois utiliser str_replace et mb_strtolower.
    D'ailleurs, tu ne dois plus t'embêter : tu encodes tout en UTF-8 sans BOM et utilises uniquement la bibliothèque unicode (fonctions mb_xxx, multibyte strings)
    Merci pour ta réponse, et je pense que le sujet est encore à creuser comme l'explique akniep at linklift dot net sur le lien http://php.net/manual/fr/function.mb-strtolower.php

    La fonction qui semble poser un problème (qui fait sauter des caractères) est array_map dans sa prise en charge d'un fichier UTF8 sans BOM sachant que sur un autre serveur (alwaysdata) cela fonctionne très bien....????

    J'ai dupliqué la base de données en localhost pour faire des tests d'encodage mais cela ne change rien.
    Le problème semble vraiment lié à la prise en charge de l'encodage du fichier :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    function sans_accents($string)
    // Retoune une chaine de caractère sans les accents
    {
        $translit = array(
            'Á' => 'A',
            'À' => 'A',
            'Â' => 'A',
            'Ä' => 'A',
            'Ã' => 'A',
            'Å' => 'A',
            'Ç' => 'C',
            'É' => 'E',
            'È' => 'E',
            'Ê' => 'E',
            'Ë' => 'E',
            'Í' => 'I',
            'Ï' => 'I',
            'Î' => 'I',
            'Ì' => 'I',
            'Ñ' => 'N',
            'Ó' => 'O',
            'Ò' => 'O',
            'Ô' => 'O',
            'Ö' => 'O',
            'Õ' => 'O',
            'Ú' => 'U',
            'Ù' => 'U',
            'Û' => 'U',
            'Ü' => 'U',
            'Ý' => 'Y',
            'á' => 'a',
            'à' => 'a',
            'â' => 'a',
            'ä' => 'a',
            'ã' => 'a',
            'å' => 'a',
            'ç' => 'c',
            'é' => 'e',
            'è' => 'e',
            'ê' => 'e',
            'ë' => 'e',
            'í' => 'i',
            'ì' => 'i',
            'î' => 'i',
            'ï' => 'i',
            'ñ' => 'n',
            'ó' => 'o',
            'ò' => 'o',
            'ô' => 'o',
            'ö' => 'o',
            'õ' => 'o',
            'ú' => 'u',
            'ù' => 'u',
            'û' => 'u',
            'ü' => 'u',
            'ý' => 'y',
            'ÿ' => 'y'
        );
        $string = strtr($string, $translit);
        return preg_replace('#[^a-zA-Z0-9\-\._]#', ' ', $string);
    }
    par la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       $El_Nom_sans_accent = array_map('sans_accents', $El_Nom); // On enlève les accents
    cf post précédent pour les fichiers de log.

    J'ai besoin de faire des tris sur des caractères non latin voire exotiques (écritures du monde).
    Mes fichiers sont déjà en UTF8 sans BOM (par facilité).

    Si un spécialiste de l'encodage peut participer à la discussion j'en serais ravi.

Discussions similaires

  1. encoder des fichiers audio
    Par thugelife dans le forum Autres Logiciels
    Réponses: 0
    Dernier message: 16/07/2009, 19h54
  2. [BATCH]script pour encoder des fichiers dans une arborescence
    Par ashgan44 dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 11/05/2009, 15h04
  3. Encoder un fichier en .avi
    Par miketidy dans le forum Vidéo
    Réponses: 4
    Dernier message: 17/09/2008, 13h44
  4. Encoder un fichier en base64
    Par drayogo dans le forum VBScript
    Réponses: 4
    Dernier message: 17/09/2008, 11h40

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