[RESOLU] exploitation fichier csv

ruben06
Invité n'ayant pas de compte PHPfrance

21 juil. 2014, 09:36

Salut a tous,

Je souhaite remplacer certaines valeurs dans un fichier CSV pour en créer un nouveau avec les valeurs remplacées.
Mon souci se trouve dans la mise en forme, je n'arrive pas avec fputcsv a remette chaque cellule a sa place vu qu'elles se mettent les une sous les autres sur la même colonne.
Voici mon code :

if (($handle = fopen("STRAX2014.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 10000, ";")) !== FALSE) {
        $num = count($data);
        for ($c = 0; $c < $num; $c++) {
            if ($data[$c] == "AEGIS") {
                $data[$c] = "Aegis";
            }
            echo $data[$c] . "<br />\n";
        }
        $fp = fopen("new.csv", "a");
        foreach ($data as $fields) {
            $val = explode(";",$fields);
            fputcsv($fp, $val);
        }
    }
    fclose($handle);
}

Merci à tous de votre aide!

Mammouth du PHP | 2278 Messages

21 juil. 2014, 09:52

Bjr,
Tu as juste un mot à remplacer par un autre? ou ce que tu montres n'est qu'un exemple.
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ruben06
Invité n'ayant pas de compte PHPfrance

21 juil. 2014, 09:54

Non ce n'est qu'un exemple j'ai pas mal de retouches a faire...

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

21 juil. 2014, 11:15

salut,

le plus simple c'est d'utiliser la fonction file (attention a la taille du fichier quand même).
dans ce cas un simple remplace sur la ligne (bien sur un faut faire attention au séparateur de champ et sauf de ligne) suffit.

pour mettre le contenu du tableau dans le fichier file_put_contents + implode

sinon pour ton code :
- tu ouvre le fichier destination à chaque ligne d'origine sans fermer ça doit pas être jolie en mémoire, voir même cela peux apporter des conflit (qui te posent peux ête problème ici.
tu n'ajoute pas de saut de saut
il faut ouvrir la ressource pour le fichier source, ouvrir celle du fichier cible et ensuite les utiliser.

je ferais quelque chose dans ce goût la
<?php
define('DEBUG', true);
$cible = fopen('fichiercible.csv', 'a');
flock($cible, LOCK_EX);
if (($source = fopen("STRAX2014.csv", "r")) !== false) {
    while (($data = fgetcsv($source, 10000, ";")) !== false) {
        $final = [];
        foreach ($data as $i => $value) {
            if ($value == "AEGIS") {
                $final[$i] = "Aegis";
            }else {
                $final[$i] = $value;
            }
            // histoire de pas polluer l'affichage si pas besoin
            if (DEBUG) {
                echo $data[$i] . "<br />\n";
            }
        }
        // insertion dans le nouveau fichier
        fputcsv($fp, $final);
    }
    fclose($source);
}

flock($cible, LOCK_UN);
fclose($cible);
 
Après il faut voir la taille des fichiers qui seront traité parce que je pense que l'on peux faire beaucoup plus simple
<?php
$source = 'STRAX2014.csv';
$cible = 'lefichierfinal.csv';
$content = file_get_contents($source);

$tabPattern = ['AEGIS', 'AUTRE', 'CHOSE'];
$tabreplace = ['Aegis', 'Autre', 'Chose'];

$withReplace = str_replace($tabPattern, $tabreplace, $content);

file_put_contents($cible, $withReplace);
je te laisse regarder la doc des fonctions utilisées afin de comprendre ce qui est fait.

@+
Il en faut peu pour être heureux ......

Mammouth du PHP | 2278 Messages

21 juil. 2014, 11:31

Bjr
Il faut ouvrir le fichier new.csv en écriture en même temps que l'autre en lecture.
Tu crées un tableau des mots à remplacer un tableau des remplaçants.
boucle
Tu parcours le fichier original comme tu fais (cad ligne par ligne) en créant à chaque fois un tableau nouvelle_ligne.
Tu remplis ce tableau en appliquans str_replace à la ligne d'origine.
Tu copies cette ligne par fputcsv
boucle
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ruben06
Invité n'ayant pas de compte PHPfrance

21 juil. 2014, 11:48

salut,

le plus simple c'est d'utiliser la fonction file (attention a la taille du fichier quand même).
dans ce cas un simple remplace sur la ligne (bien sur un faut faire attention au séparateur de champ et sauf de ligne) suffit.

pour mettre le contenu du tableau dans le fichier file_put_contents + implode

sinon pour ton code :
- tu ouvre le fichier destination à chaque ligne d'origine sans fermer ça doit pas être jolie en mémoire, voir même cela peux apporter des conflit (qui te posent peux ête problème ici.
tu n'ajoute pas de saut de saut
il faut ouvrir la ressource pour le fichier source, ouvrir celle du fichier cible et ensuite les utiliser.

je ferais quelque chose dans ce goût la
<?php
define('DEBUG', true);
$cible = fopen('fichiercible.csv', 'a');
flock($cible, LOCK_EX);
if (($source = fopen("STRAX2014.csv", "r")) !== false) {
    while (($data = fgetcsv($source, 10000, ";")) !== false) {
        $final = [];
        foreach ($data as $i => $value) {
            if ($value == "AEGIS") {
                $final[$i] = "Aegis";
            }else {
                $final[$i] = $value;
            }
            // histoire de pas polluer l'affichage si pas besoin
            if (DEBUG) {
                echo $data[$i] . "<br />\n";
            }
        }
        // insertion dans le nouveau fichier
        fputcsv($fp, $final);
    }
    fclose($source);
}

flock($cible, LOCK_UN);
fclose($cible);
 
Après il faut voir la taille des fichiers qui seront traité parce que je pense que l'on peux faire beaucoup plus simple
<?php
$source = 'STRAX2014.csv';
$cible = 'lefichierfinal.csv';
$content = file_get_contents($source);

$tabPattern = ['AEGIS', 'AUTRE', 'CHOSE'];
$tabreplace = ['Aegis', 'Autre', 'Chose'];

$withReplace = str_replace($tabPattern, $tabreplace, $content);

file_put_contents($cible, $withReplace);
je te laisse regarder la doc des fonctions utilisées afin de comprendre ce qui est fait.

@+

Merci, ton deuxième code marche nickel :D je vais en effet fouillé la doc pour voir comment ça marche précisément.

ruben
Invité n'ayant pas de compte PHPfrance

21 juil. 2014, 11:58

Autre question,

pensez vous qu'il soit possible d'établir une règle précisant que si je trouve tel mot dans une cellule, je remplace ce mot par un autre dans une autre colonne mais sur la même ligne, exemple :

Image

Ici, à la ligne de la ref 17507, comme le mot 'HTC' est présent dans la colonne B, je remplacerais la marque (actuellement AEGIS) par HTC

Merci encore!

Mammouth du PHP | 2278 Messages

21 juil. 2014, 12:47

@moogli d'abord:
connais-tu : http://www.mon-code.net/article/49/lire ... pl-de-php5 et si oui as-tu un avis?
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

21 juil. 2014, 16:30

@ruben : oui c'est tout a fait possible.
mais dans ce cas il faut utiliser la chose ligne par ligne et non plus globale comme pour le dernier code.
donc soit avec file, soit avec fopen et consor.

@sirakawa ; du tout, effectivement je pourrais me tourner vers ce type de classe étant donnée que je m'en suis suis fait une similaire.
reste a voir les limites d'utilisation comme la taille des données maximal utilisable.
Cela simplifie largement le code.
<?php
<?php
$source = new SplFileObject('source.csv','r');
$source->setFlags(SplFileObject::READ_CSV);
$source->setCsvControl(';', '"', '"');
$cible = new SplFileObject('cible.csv','w');
foreach($source as $line){
    print_r($line);
    // modification de la ligne avec x règles de gestions le tout fait pas une fonction 
    $line = csvrule($line);
    $cible->fputcsv($line,',');
}
c'est quand même plus sympa à lire ;)

Normalement le coté perf devrait être la vu que c'est du natif.
C'est un peu dommage que l'on ne parle pas plus souvent des classes Spl c'est pas mal.

Merci pour l'info.

@+
Il en faut peu pour être heureux ......

ruben06
Invité n'ayant pas de compte PHPfrance

21 juil. 2014, 17:48

Oui je m'en doutais que je devais passer par l’itération pour ce type de traitement...
Mais je n'ai aucune idée de comment m'y prendre dans le code, tu pense pouvoir me mettre sur la voie?


Merci

Mammouth du PHP | 2278 Messages

22 juil. 2014, 08:14

Tu pux partir de ce cpde (qui développe ma première réponse):
<?PHP
$anciens = array("AEGIS", "BIDULOS");
$nouveaux  = array("Aegis", "Bidulos");
 $fp = fopen("new2.csv", "w+");
if (($handle = fopen("truc.csv", "r")) !== FALSE) 
{
     while (($ligne = fgetcsv($handle, 10000, ";")) !== FALSE) 
	{
	     $nouvelle_ligne = array();
	    $nouvelle_ligne = str_replace($anciens, $nouveaux, $ligne); //en modifiant cette ligne
                 fputcsv($fp, $nouvelle_ligne , ";");
      }
}
     fclose($handle);

?>
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ruben06
Invité n'ayant pas de compte PHPfrance

22 juil. 2014, 11:19

Tu pux partir de ce cpde (qui développe ma première réponse):
<?PHP
$anciens = array("AEGIS", "BIDULOS");
$nouveaux  = array("Aegis", "Bidulos");
 $fp = fopen("new2.csv", "w+");
if (($handle = fopen("truc.csv", "r")) !== FALSE) 
{
     while (($ligne = fgetcsv($handle, 10000, ";")) !== FALSE) 
	{
	     $nouvelle_ligne = array();
	    $nouvelle_ligne = str_replace($anciens, $nouveaux, $ligne); //en modifiant cette ligne
                 fputcsv($fp, $nouvelle_ligne , ";");
      }
}
     fclose($handle);

?>
Merci sirakawa,

c'est ce que j'ai fait, j'ai juste rajouter un troisieme parametre ";" a fputcsv pour regler mon soucis de valeur sur la meme colonne ;)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

22 juil. 2014, 11:27

Modération :
Puisque ta question est résolue, je l'indique en cliquant sur le bouton "Mettre le sujet en tant que Résolu" pour que les futures personnes qui voudront consulter ce sujet sachent qu'il contient une solution.

Tu peux réaliser cette opération toi-même en cliquant sur le bouton vert situé en haut de la page à côté du titre, si tu as posté le 1er message en tant que membre (inscrit et identifié).

Alors... inscris-toi !!! ;)
Il en faut peu pour être heureux ......