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 :

Manipulation de chaine de caractères avec \n


Sujet :

Langage PHP

  1. #1
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut Manipulation de chaine de caractères avec \n
    Bonjour,

    Dans mon code html/php, je passais à une fonction php une chaine de caractères avec des \n pour figurer un saut de ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php 
    function display_tableau($texte_image)
    {
        $texte = "$texte_image";
        print '<h4>' . nl2br(htmlspecialchars($texte)) . '</h4>';
    ...
    ?>
    ...
    <?php 
    display_tableau("Acrylique sur toile\n2023\n40x40");
    ?>
    Dans ma page HTML, s'affichait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Acrylique sur toile
    2023
    40x40
    A présent, je lis le texte à partir d'un fichier texte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
            $fic = fopen($fichier, 'rb');
     
            while($tab=fgetcsv($fic,1024,',')) {
                  ...
                  $texte = $tab[3];
                  print '<figure class="row">';
                  print '  <figcaption>';
                  print '<h4>' . nl2br(htmlspecialchars($texte)) . '</h4>';
             ...
    Dans ma page HTML, s'affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Acrylique sur toile\n2023\n40x40
    Qu'est ce qui fait que le comportement soit modifié?
    Merci

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 104
    Points : 8 222
    Points
    8 222
    Billets dans le blog
    17
    Par défaut
    Il faut voir comment sont codés les retours à la ligne dans ton CSV.
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  3. #3
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Comment je vois cela?
    Mon csv est un fichier texte non issu d'un outil : ce sont seulement des champs séparés par une ','.
    Donc, je ne pense pas qu'il y ait d'encodage : \n corresponds aux deux caractères \ et n , non? Rien trouvé sur le net.
    Merci

  4. #4
    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
    Un fichier texte ou csv (qui est un fichier texte) contient du texte brut donc un antislash suivi d'un n est un antislash suivi d'un n et ne représente rien d'autre. Par contre dans une chaîne définie entre double-quotes en PHP, la séquence \n est interprétée comme étant un saut de ligne.
    Donc si tu veux un saut de ligne dans un fichier texte, il faut aller à la ligne et c'est tout!

    Dans un csv, il y a une subtilité supplémentaire à prendre en compte: le saut de ligne est le séparateur d'enregistrements. Donc pour figurer un saut de ligne dans une colonne, celle-ci doit-être protégée par des quotes. Par exemple:
    Code txt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    11,machin,truc,pastel,1985,5
    12,toto,pouet,"Acrylique sur toile
    2023
    40x40",1984,12
    13,bidule,bip,gouache,1992,4
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 104
    Points : 8 222
    Points
    8 222
    Billets dans le blog
    17
    Par défaut
    \n corresponds aux deux caractères \ et n , non?
    En conséquence de quoi ce ne sont plus des retours à la ligne, mais de simples littéraux.

    Le retour à la ligne \n représente un caractère bien particulier, le LINE-FEED => 0x0A (LF)

    Par contre le texte en toute lettre '\n' n'est rien d'autre que la suite d'octets 0x5C (pour \) et 0x6E (pour n) et n'a plus rien à voir avec un retour à la ligne.

    Il faut revoir le codage de ton CSV.
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    It's important to remember that this function does NOT replace newlines with <br> tags. Rather, it inserts a <br> tag before each newline, but it still preserves the newlines themselves!
    Source: https://www.php.net/manual/en/function.nl2br.php

  7. #7
    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
    C'est vrai que le coté "droit au but" (right to the point) de l'anglais manque cruellement sur cette page du manuel PHP dans la version française où l'on a traduit "before all newlines" par "à chaque nouvelle ligne" (du coup on ignore si <br /> est inséré avant ou aprés). De plus le nom de la fonction laisse supposer qu'il y a remplacement et non insertion d'où la pertinence du commentaire de CGameProgrammer at gmail dot com.

    D'autre part, je trouve particulièrement curieux que cette fontion considère que \n\r est une séquence de saut de ligne. Je ne doute pas que celle-ci existe sur je ne sais quel OS (Acorn BBC, RISC OS), mais si tel est le cas, celle-ci est quand même sacrément exotique. (ceci étant dit, pour une imprimante matricielle, \r\n ou \n\r ça ne change rien). Et pourquoi pas x85 NEL (Next Line), le saut du ligne de l'OS400!
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  8. #8
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    A CosmoKnacki : mais une ligne csv est définie normalement comme se terminant par un crlf, donc si j'écris ma ligne csv comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    12,toto,pouet,"Acrylique sur toile
    2023
    40x40",1984,12
    C'est 3 lignes du fichier que je devrais lire pour avoir mon information! Et comment savoir le nombre de csv de mon champ? Ce n'est pas exploitable.


    Le fond du problème est que dans la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print '<h4>' . nl2br(htmlspecialchars($texte)) . '</h4>';
    $texte a deux origines :
    - soit c'est le contenu de la chaine "Acrylique sur toile\n2023\n40x40" passé en paramètre de la fonction display_tableau()
    - soit c'est le contenu de la ligne du fichier csv et étant donné que sur la page html écrit Acrylique sur toile\n2023\n40x40 avec \n, c'est qu'il n'y a pas eu d'interprétation du \n et la fonction nl2br n'a pas joué son rôle.

    Je ne me l'explique pas.

  9. #9
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Pour m'en sortir, une solution "bourrin" consisterait à découper ma chaine de caractères en fonction du séparateur \n et écrire <br> là ou il ya \n.

  10. #10
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Dans le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
         $texte = "Acrylique sur toile\n2023\n40x40";
                  print $texte;
    Ma page html affiche:
    Acrylique sur toile 2023 40x40

    Qu'en pensez vous?
    Merci

  11. #11
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Marre de tourner en rond.
    Exit le \n dans ma chaine de caractères, je met le séparateur @.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
         $texte = $tab[3];
                  $nb = substr_count($texte, '@');
                  $t_texte = explode("@", $texte);
                  print '<h4>';
                  for ($i = 0; $i <= $nb; $i++) {
                    print htmlspecialchars($t_texte[$i]);
                    print '<br>';
                  }
                  print '</h4>';
    Ca marche et c'est le principal.

  12. #12
    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
    Citation Envoyé par awalter1 Voir le message
    A CosmoKnacki : mais une ligne csv est définie normalement comme se terminant par un crlf, donc si j'écris ma ligne csv comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    12,toto,pouet,"Acrylique sur toile
    2023
    40x40",1984,12
    C'est 3 lignes du fichier que je devrais lire pour avoir mon information! Et comment savoir le nombre de csv de mon champ? Ce n'est pas exploitable.
    Première nouvelle!

    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
    $csv = <<<'CSV'
    11,machin,truc,pastel,1985,5
    12,toto,pouet,"Acrylique sur toile
    2023
    40x40",1984,12
    13,bidule,bip,gouache,1992,4
    CSV;
     
    $path = 'data:text/plain;base64,' . base64_encode($csv);
     
    $count = 0;
     
    if (false !== $handle = fopen($path, 'r')) {
        while(false !== $cols = fgetcsv($handle)) {
            echo "|{$cols[3]}|\n";
            $count++;
        }
    }
     
    echo "\nnombre d'enregistrements: $count";
    demo

    Comme je l'ai expliqué dans mon premier post les doubles quotes sont utilisés dans le csv pour protéger ces sauts de ligne. De cette manière, il n'y a pas d'ambiguïté avec le séparateur d'enregistrements.
    fgetcsv sait parfaitement gérer ça, car il ne lit pas ligne par ligne comme tu le supposes mais enregistrement par enregistrement. Ça t'évitera le vilain bricolage que tu t'apprêtes à faire!
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 104
    Points : 8 222
    Points
    8 222
    Billets dans le blog
    17
    Par défaut
    Ca marche et c'est le principal.
    Et le jour où ton texte aura des @ tu feras comment ?
    Il existe des fonctions PHP pour créer (fputcsv()) et lire (fgetcsv()) les CSV, utilise-les !
    Une valeur CSV peut contenir des (vrais) retours à la ligne, il n'y a aucun problème, voir les réponses de CosmoKnacki.
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  14. #14
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Citation Envoyé par awalter1 Voir le message
    Pour m'en sortir, une solution "bourrin" consisterait à découper ma chaine de caractères en fonction du séparateur \n et écrire <br> là ou il ya \n.
    Il n'y a rien de bourrin, c'est même ce qui est suggéré dans la page de documentation que j'ai quoté précédemment:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str_replace( "\n", '<br />', $Text );
    ou plutôt (non testé):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str_replace( "\n", '<br />', htmlspecialchars($Text ));
    Car vous pouvez avoir des caractères qui ne s'afficheraient pas correctement à l'état brut, je pense aux quotes, > < mais pas seulement.

  15. #15
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    fgetcsv[/c] sait parfaitement gérer ça, car il ne lit pas ligne par ligne comme tu le supposes mais enregistrement par enregistrement.
    Mais comment est signalé la fin de l'enregistrement? Dans les langages que j'utilisais (LTR, C, python) je ne me souviens pas d'une telle fonction.

    Citation Envoyé par Séb. Voir le message
    Et le jour où ton texte aura des @ tu feras comment ?
    Oui je sais tu as raison sur le fond, mais je suis maitre du fichier et c'est à moi d'interdire ce caractère pour ce champ dans les spécifications du fichier.

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 104
    Points : 8 222
    Points
    8 222
    Billets dans le blog
    17
    Par défaut
    Citation Envoyé par awalter1 Voir le message
    Oui je sais tu as raison sur le fond, mais je suis maitre du fichier et c'est à moi d'interdire ce caractère pour ce champ dans les spécifications du fichier.
    Tu ajoutes des contraintes à ton fichier, des contraintes qui n'existent pas dans CSV. C'est dommage !

    Citation Envoyé par awalter1 Voir le message
    Mais comment est signalé la fin de l'enregistrement? Dans les langages que j'utilisais (LTR, C, python) je ne me souviens pas d'une telle fonction.
    Dans un fichier CSV le retour à la ligne hors valeur indique la fin de l'enregistrement. Typiquement une valeur est délimitée par des ".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $csv_options = ['separator' => ',', 'enclosure' => '"', 'escape' => ''];
    fputcsv($stream, ['valeur 1', "valeur 2\r\nmultiligne", 'valeur 3'], ...$csv_options);
    Produit le fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    "valeur 1","valeur 2
    multiligne","valeur 3"
    Grâce au délimiteur " le retour à la ligne sera correctement interprété comme partie intégrante de la 2e valeur lors du décodage par fgetcsv(). Teste !
    Un problème exposé clairement est déjà à moitié résolu
    Keep It Smart and Simple

  17. #17
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Citation Envoyé par Séb. Voir le message
    Dans un fichier CSV le retour à la ligne hors valeur indique la fin de l'enregistrement. Typiquement une valeur est délimitée par des ".
    Historiquement, le csv est né avec le tableur excel de Microsoft. Aujourd'hui encore, lorsque tu exportes ton fichier au format csv, il n'y a pas de " encadrant la valeur des champs sauf si tu imposes de les mettre et là tu imposes une contrainte

    Citation Envoyé par binarygirl Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str_replace( "\n", '<br />', $Text );
    Bonjour,
    Ta solution ne marche pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
           <?php 
            $rep = $_GET['nom'];
            $fic = fopen("medias/liste-tableaux-1.csv", 'rb');
            $full_rep = "medias/" . $rep . "/";
            while($tab=fgetcsv($fic,1024,';')) {
                if ($rep == $tab[1]) {
                  $titre = $tab[0];
                  $image = $tab[2];
                  $texte = $tab[3];
                  print '<figure class="row">';
                  print '  <figcaption>';
                  print '<h2>' . htmlspecialchars($titre) . '</h2>';
                  print '<h4>' . str_replace( "\n", '<br />', $tab[3]) . '</h4>';
    ...
    Ligne du fichier : Collision quantique;AW;collision_quantique_120x40.jpg;Acrylique sur toile\n2023\n120x40;
    L'affichage dans la page donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Collision quantique
    Acrylique sur toile\n2023\n120x40

  18. #18
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Citation Envoyé par awalter1 Voir le message
    Bonjour,
    Ta solution ne marche pas :
    En fait il faut escape le backslash à cause de l'interpolation de string entre double quotes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str_replace( "\\n", '<br />', $texte)
    ou bien procéder avec single quotes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str_replace( '\n', '<br />', $texte)

  19. #19
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Bien vu! ça fonctionne
    Merci

  20. #20
    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
    Citation Envoyé par awalter1
    Aujourd'hui encore, lorsque tu exportes ton fichier au format csv, il n'y a pas de " encadrant la valeur des champs sauf si tu imposes de les mettre et là tu imposes une contrainte
    Pas du tout. Il ne s'agit pas de mettre entre quotes chaque colonne, mais uniquement lorsque c'est nécessaire. Et ça, Excel le fait automatiquement lorsque tu exportes en csv et qu'une cellule contient un saut de ligne.

    Citation Envoyé par awalter1
    Dans les langages que j'utilisais (LTR, C, python) je ne me souviens pas d'une telle fonction.
    Dans ce cas c'est que tu l'as raté! Parce que dans tous les langages un peu évolués tu trouveras soit une fonction équivalente intégrée au langage ou un module qui la propose.

    En C, tu trouveras des bibliothèques csv à la pelle, en Python tu as la fonction csv.reader du module csv, en TCL idem (LTR ? C'est quoi ça? Tu veux dire TCL ?).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Dégradé sur une chaine de caractères avec 3 a 4 couleurs
    Par avogadro dans le forum Composants VCL
    Réponses: 6
    Dernier message: 31/03/2006, 13h21
  2. Reception chaine de caractère avec recvfrom()
    Par innosang dans le forum C
    Réponses: 5
    Dernier message: 31/12/2005, 14h51
  3. Lecture d'une chaine de caractère avec fgets
    Par mayoouketchup dans le forum Langage
    Réponses: 9
    Dernier message: 22/12/2005, 16h17
  4. Réponses: 4
    Dernier message: 20/08/2004, 10h59
  5. Réponses: 2
    Dernier message: 06/12/2002, 07h50

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