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 :

La présence du caractère \ et dernière cellule vide dans une ligne du fichier CSV fait planter fgetcsv


Sujet :

Langage PHP

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    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 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut La présence du caractère \ et dernière cellule vide dans une ligne du fichier CSV fait planter fgetcsv
    Bonjour,

    je lis des fichiers CSV avec la fonction fgetcsv et je fais avec chaque ligne lue un traitement avec array_combine :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (($row = fgetcsv(self::$handle, $buffer, self::$separator, $enclosure)) !== false) {
                    self::$data[] = array_combine(self::$header, $row);
                }

    self::$header contient la première ligne du fichier CSV. Pour que array_combine fonctionne, il faut que les 2 tableaux (self::$header et $row) aient la même longueur. Le souci est que si le caractère \ est présent en fin d'une cellule d'une ligne du fichier CSV et que la dernière cellule est vide, la fonction fgetcsv ne lit pas les cellules suivantes de la ligne...donc évidemment, array_combine échoue.

    Le caractère d'enclosure (ou encadrement) est ".

    contenu d'une ligne du CSV qui fait planter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Mois de Months;Resolution;Resolution OLA Status;Resolution Op Cat Calculated
    oct-21;"ISSUE: Outlook - Issue
    CAUSE: user calling regarding Outlook, that every time the user tries to delete an email, it takes long time
    RESOLUTION: screen share
    CMD:
    Cleaned %SystemRoot%\";2;
    contenu du header :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    array(4) {
      [0]=>
      string(14) "mois de months"
      [1]=>
      string(10) "resolution"
      [2]=>
      string(21) "resolution ola status"
      [3]=>
      string(28) "resolution op cat calculated"
    }
    Les 4 cellules données par le header sont bien présentes dans la ligne du CSV. (bien noter que la dernière est vide)

    Ligne $row retournée par fgetcsv:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    array(2) {
      [0]=>
      string(6) "oct-21"
      [1]=>
      string(189) "ISSUE: Outlook - Issue
    CAUSE: user calling regarding Outlook, that every time the user tries to delete an email, it takes long time
    RESOLUTION: screen share
    CMD:
    Cleaned %SystemRoot%\";2;
    "
    }
    Quand fgetcsv a lu le CSV, il a ignoré le caractère d'encadrement ($enclosure) et donc au lieu de voir 4 cellules, il n'en a vu que 2.

    Comment résoudre cela, SVP ?

    A noter, qu'il n'y a pas de bug si la dernière cellule de la ligne n'est pas vide ou si le caractère \ ne termine pas la 2e cellule.

  2. #2
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 269
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 269
    Points : 8 568
    Points
    8 568
    Billets dans le blog
    17
    Par défaut
    Essaie en désactivant l'échappement propriétaire, 5e argument vide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (($row = fgetcsv(self::$handle, $buffer, self::$separator, $enclosure, '')) !== false) {

  3. #3
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    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 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Excellent ; ça marche. Mais la doc indique juste qu'un argument vide désactive le mécanisme d'échappement propriétaire
    escape

    Le paramètre optionnel escape définit le caractère d'échappement (au plus un caractère d'un seul octet). Une chaîne de caractères vide ("") désactive le mécanisme d'échappement propriétaire.
    Pourquoi ça résoud mon problème ?

  4. #4
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 269
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 269
    Points : 8 568
    Points
    8 568
    Billets dans le blog
    17
    Par défaut
    Par défaut le \ est considéré par fgetcsv() comme un caractère d'échappement du délimiteur
    (ce qui est propriétaire, l'échappement du " devant être effectué avec un autre ")

    Or dans ton cas le \ ne doit pas échapper le " => On désactive l'échappement propriétaire

  5. #5
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    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 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Merci pour l'explication.
    Néanmoins, j'ai du mal à suivre.

    ce qui est propriétaire, l'échappement du " devant être effectué avec un autre "
    qu'est-ce que tu veux dire ?
    En outre, ça marchait si la dernière cellule n'est pas vide ; pourquoi ?

  6. #6
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 269
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 269
    Points : 8 568
    Points
    8 568
    Billets dans le blog
    17
    Par défaut
    qu'est-ce que tu veux dire ?
    Qu'est-ce que tu ne comprends pas ?

    En outre, ça marchait si la dernière cellule n'est pas vide ; pourquoi ?
    Le parser CSV est gentil et essaie de rattraper le coup.

  7. #7
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    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 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Séb. Voir le message
    (ce qui est propriétaire, l'échappement du " devant être effectué avec un autre ")
    c'est quoi qui est propriétaire ? Et en fait, je ne comprends pas le concept de mécanisme d'échappement propriétaire.

    échapper un " avec un autre " ? Le seul échappement que je connaisse est fait avec un \ . Donc échapper autrement, ça me dépasse.

  8. #8
    Membre éprouvé Avatar de Willy_k
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2011
    Messages
    540
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2011
    Messages : 540
    Points : 1 067
    Points
    1 067
    Par défaut
    Bonjour,

    Comment est généré ce csv pour avoir ce genre de situation ? Le problème ne devrait-il pas être corrigé en amont ?

  9. #9
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    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 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    C'est vrai que c'est pas super clean, mais j'y peux rien : j'hérite d'extracts de bdd faits par d'autres (au format CSV), je récupère les données et les traite.

  10. #10
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 269
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 269
    Points : 8 568
    Points
    8 568
    Billets dans le blog
    17
    Par défaut
    Citation Envoyé par laurentSc Voir le message
    c'est quoi qui est propriétaire ?
    L'échappement CSV avec un \

    échapper un " avec un autre " ?
    Oui, c'est comme ça qu'on est censé faire en CSV
    Voir le point 2.7 => https://datatracker.ietf.org/doc/html/rfc4180#section-2

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       7.  If double-quotes are used to enclose fields, then a double-quote
           appearing inside a field must be escaped by preceding it with
           another double quote.  For example:
     
           "aaa","b""bb","ccc"
    Le seul échappement que je connaisse est fait avec un \ . Donc échapper autrement, ça me dépasse.
    La méthode d'échappement dépend du langage/de la techno.
    En C / PHP / JavaScript / etc. on utilise \ pour échapper
    En SQL on utilise '
    Avec CSV on utilise "

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 07/07/2018, 23h33
  2. Réponses: 3
    Dernier message: 21/08/2015, 12h19
  3. [XL-2003] Sélectionner la dernière cellule vide d'une plage de cellule
    Par kikie43 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 23/12/2014, 14h30
  4. [XL-2000] Détection d'une cellule vide dans une ligne.
    Par babou41287 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/04/2012, 16h40
  5. recherche de la 1ère cellule vide dans une ligne
    Par ericberg dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 26/10/2010, 21h53

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