[RESOLU] Parser un répertoire de fichiers DATA pour intégration MySQL

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Parser un répertoire de fichiers DATA pour intégration MySQL

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 11 oct. 2013, 11:02

Alleluia !!!!!!!!!!
Merci Moogli!!!!!
Tout fonctionne à merveille!!!!!
=D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D>
Je teste sur mon serveur et indique résolu si tout roule

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 10 oct. 2013, 21:29

aller avec des neurones un peu plus en forme je regarde la doc et je vois la description sommaire des méthodes de l'objet DirectoryIterator
DirectoryIterator::getBasename() - Lit le nom de dossier de l'élément DirectoryIterator
DirectoryIterator::getFilename() - Retourne le nom de l'entrée courante du dossier
DirectoryIterator::getPath() - Retourne le chemin du dossier
pathinfo() - Retourne des informations sur un chemin système
sachant le nom du fichier courant est obtenu avec $fileinfo->getFilename() et que le chemin complet est obtenue avec $fileinfo->getPath() (sans / final) je dirais donc que le déplacement initial est
<?php
rename($originalDir . $fileinfo->getFilename(), $tmpFolder . $fileinfo->getFilename());
le final
<?php
rename($tmpFolder . $fileinfo->getFilename(), $finalFolder . $fileinfo->getFilename());
le tous dans le code un peu plus clair
<?php
try {
    // connexion
    $pdo = new PDO('mysql:host=localhost;dbname=josse34', 'josse34', 'josse34');
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);

    $tmpFolder = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
    $finalFolder = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'final' . DIRECTORY_SEPARATOR;
    $originalDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'avant' . DIRECTORY_SEPARATOR;

    $dir = new DirectoryIterator($originalDir);
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() == 'data') {
            echo 'parse du fichier : ' . $fileinfo->getFilename() . '<br />';

            rename($originalDir . $fileinfo->getFilename(), $tmpFolder . $fileinfo->getFilename());

            $tabFile = file($tmpFile);
            preg_match('/^fic(\d+)-(\d+)-(\d+)-(\d+).data$/', $fileinfo->getFilename(), $match);
            $table = $match[1];
            $stmt = $pdo->prepare('INSERT INTO `' . $table . '` (poste,dtlog, glot) VALUES (:poste,str_to_date(:dt,\'%Y%m%d\'),:glot)');
            if (count($tabFile) > 0) {
                unset($tabFile[0]);
                $i = 0;
                foreach ($tabFile as $line) {
                    $csv = str_getcsv($line, ';');
                    $stmt->bindValue(':poste', $csv[0], PDO::PARAM_INT);
                    $stmt->bindValue(':dt', $csv[1]);
                    $stmt->bindValue(':glot', $csv[2], PDO::PARAM_INT);
                    $stmt->execute();
                    echo 'insertion de la ligne ' . $i . '<br />';
                    $i++;
                }
            }
        }
        rename($tmpFolder . $fileinfo->getFilename(), $finalFolder . $fileinfo->getFilename());
    }
} catch (Exception $e) {
    echo $e->getMessage() . '<br />' . $e->getTraceAsString();
}
@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 09 oct. 2013, 13:30

Navré, j'ai beau essayer toutes les combinaisons, quelque chose m'échappe pour les rename des lignes 13 et 30 (d'ailleurs ce code ne fonctionne absolument pas, rien n'est déplacé à contrario de l'utilisation de $fileinfo seul)!
Pour moi ça devrait bien etre rename("./AVANT/$fileinfo", "./PENDANT/$fileinfo"); et non pas avec $fileinfo->getPathname().
<?php
try {
    // connexion
    $pdo = new PDO('mysql:host=localhost;dbname=labase', 'PDO', '290585');
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);

    $dir = new DirectoryIterator(dirname(__FILE__) . '\AVANT');  
    foreach ($dir as $fileinfo) { 
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() == 'data') {
            rename("./AVANT/$fileinfo->getPathname()", "./PENDANT/$fileinfo->getPathname()");
            echo 'parse du fichier : '.$fileinfo->getFilename().'<br />';
            $tabFile = file($fileinfo->getPathname());
            preg_match('/^fic(\d+)-(\d+)-(\d+)-(\d+).data$/',$fileinfo->getFilename(),$match);
            $table = $match[1];
            $pdo->query("CREATE TABLE IF NOT EXISTS `$table` (dtlog  INT PRIMARY KEY, glot INT);");
            $stmt = $pdo->prepare('INSERT INTO `'.$table.'` (dtlog, glot) VALUES (str_to_date(:dt,\'%Y%m%d\'),:glot) ON DUPLICATE KEY UPDATE glot = VALUES(glot)');
            if (count($tabFile) > 0) {
                unset($tabFile[0]);
                $i = 0;
                foreach ($tabFile as $line) {
                    $csv = str_getcsv($line, ';');
                    $stmt->bindValue(':dt', $csv[1]);
                    $stmt->bindValue(':glot', $csv[2], PDO::PARAM_INT);
                    $stmt->execute();
                    echo 'insertion de la ligne '.$i.'<br />';
                    $i++;
                    rename("./PENDANT/$fileinfo->getPathname()", "./APRES/$fileinfo->getPathname()");
                }
            }
        }
    }
} catch (Exception $e) {
    echo $e->getMessage() . '<br />' . $e->getTraceAsString();
}
Notice: Undefined property: DirectoryIterator::$getPathname in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata5.php on line 13

Notice: Undefined property: DirectoryIterator::$getPathname in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata5.php on line 13

Warning: rename(./AVANT/(),./PENDANT/()): in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata5.php on line 13
parse du fichier : fic34154001-2013-10-03.data
insertion de la ligne 0

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 08 oct. 2013, 22:37

oui si dtlog n'est pas une colonne unique (unique ou pk) effectivement ce que tu as fait ne peux fonctionner ;)

ensuite le message indique que le fichier n'existe pas, j'ai tendance à croire php dans ce cas ;)

pourquoi ?

parce que le nom du fichier c'est $fileinfo->getPathname() et pas fileinfo, regarde la doc ;)


@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 07 oct. 2013, 17:04

Bonjour!
Bon j'en suis la et j'avance pas trop mal :
try {
    // connexion
    $pdo = new PDO('mysql:host=localhost;dbname=labase', 'PDO', '290585');
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);

    $dir = new DirectoryIterator(dirname(__FILE__) . '\AVANT');  
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() == 'data') {
            //rename("./AVANT/$fileinfo", "./PENDANT/$fileinfo");
            echo 'parse du fichier : '.$fileinfo->getFilename().'<br />';
            $tabFile = file($fileinfo->getPathname());
            preg_match('/^fic(\d+)-(\d+)-(\d+)-(\d+).data$/',$fileinfo->getFilename(),$match);
            $table = $match[1];
            $pdo->query("CREATE TABLE IF NOT EXISTS `$table` (dtlog INT, glot INT);");
            $stmt = $pdo->prepare('INSERT INTO `'.$table.'` (dtlog, glot) VALUES (str_to_date(:dt,\'%Y%m%d\'),:glot) on duplicate key update glot=:glot');
            if (count($tabFile) > 0) {
                unset($tabFile[0]);
                $i = 0;
                foreach ($tabFile as $line) {
                    $csv = str_getcsv($line, ';');
                    $stmt->bindValue(':dt', $csv[1]);
                    $stmt->bindValue(':glot', $csv[2], PDO::PARAM_INT);
                    $stmt->execute();
                    echo 'insertion de la ligne '.$i.'<br />';
                    $i++;
                    //rename("./PENDANT/$fileinfo", "./APRES/$fileinfo");
                }
            }
        }
    }
} catch (Exception $e) {
    echo $e->getMessage() . '<br />' . $e->getTraceAsString();
}
J'ai viré la première colonne "poste" et réussi à créer la table si elle n'existe pas par :
$pdo->query("CREATE TABLE IF NOT EXISTS `$table` (dtlog INT, glot INT);");
Pour mettre à jour automatiquement la valeur si déjà présente dans la table, je sais qu'il faut utiliser INSERT INTO ... ON DUPLICATE KEY UPDATE mais je fais une erreur avec le dernier paramètre glot=:glot, est ce parce que je n'ai pas défini de PRIMARY KEY ? :
$stmt = $pdo->prepare('INSERT INTO `'.$table.'` (dtlog, glot) VALUES (str_to_date(:dt,\'%Y%m%d\'),:glot) on duplicate key update glot=:glot');
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?=?' at line 1
#0 C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata5.php(19): PDO->prepare('INSERT INTO `34...') #1 {main}
Pour déplacer le fichier, je bloque également en ce qui concerne l'utilisation du fichier déplacé. Avec le
rename("./AVANT/$fileinfo", "./PENDANT/$fileinfo");
avant traitement et le
rename("./PENDANT/$fileinfo", "./APRES/$fileinfo");
après traitement.
Warning: file(C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\AVANT\fic34154001-2013-10-03.data): failed to open stream: No such file or directory in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata5.php on line 15
Merci!!!

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 06 oct. 2013, 18:55

Slu!
Pour le déplacement il faut utiliser la fonction rename
C'est la première chose a faire dans le 1er foreach (juste après le if) et ensuite il faut utiliser le fichier temporaire ;)
Pour ce qui est du déplacement du dossier "AVANT" à "PENDANT" durant le traitement, si je fais cela :
$dir = new DirectoryIterator(dirname(__FILE__) . '\AVANT');  
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() == 'data') {
            rename("./AVANT/$fileinfo", "./PENDANT/$fileinfo");
            echo 'parse du fichier : '.$fileinfo->getFilename().'<br />';
            $tabFile = file($fileinfo->getPathname());
            preg_match('/^fic(\d+)-(\d+)-(\d+)-(\d+).data$/',$fileinfo->getFilename(),$match);
            $table = $match[1];
            $stmt = $pdo->prepare('INSERT INTO `'.$table.'` (poste,dtlog, glot) VALUES (:poste,str_to_date(:dt,\'%Y%m%d\'),:glot)');
Ca déplace le fichier mais il ne le trouve plus pour le FOREACH et du coup, ne le traite pas SQL ni le déplace de "PENDANT" à "APRES" via rename("./PENDANT/$fileinfo", "./APRES/$fileinfo"); !!!
Warning: file(C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\AVANT\fic34154001-2013-10-03.data): failed to open stream: No such file or directory in C:\Program Files (x86)\EasyPHP-DevServer-13.1VC11\data\localweb\scripts\testparserdata4.php on line 15
Je ne parviens pas à utiliser le fichier déplacé.

Un fichier représente 40,3 octets en moyenne, soit un maxima théorique durant de traitement de 600 fichiers * 40,3 octets = 25Ko, largement soutenable!!!

Oh, et puis est il possible de tester la table avant pour voir si une ligne avec la même date existe déjà et dans ce cas remplacer la valeur?!?!?!?!
Peut etre un truc du genre à intercaler avant le $stmt->execute(); d'injection :
$count = $dbh->prepare('SELECT COUNT(*) FROM `'.$table.'` WHERE dt = :dt');
$count->bindValue('dt', $_POST['dt'], PDO::PARAM_STR);
$count->execute();
if ($count->fetchColumn()) {
    //ON METS A JOUR LA VALEUR, MAIS COMMENT???
} else {
   //ON INJECTE NORMALEMENT CAR LA LIGNE N'EXISTE PAS, avec $stmt->execute();
}
Merci!!

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 06 oct. 2013, 13:23

Yop,

Pour le déplacement il faut utiliser la fonction rename
C'est la première chose a faire dans le 1er foreach (juste après le if) et ensuite il faut utiliser le fichier temporaire ;)

Et ensuite pareil mais du temporaire vers l'archive.

Pour le volume ce n'est pas forcément un problème, ce qui peux en être un c'est la taille du fichier.
Avec ce système tu charge le fichier entièrement en mémoire et tu est limité en mémoire utilisable par ton script (memory limit dans un phpinfo) et si tu dépasse cette taille il faudra changer ton fusil d'épaule et le lire au fur et a mesure comme tu l'as fait au début ;)

@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 05 oct. 2013, 19:39

Ce n'est pas une version fonctionnelle, c'est une version MERVEILLEUSE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! =D>

Incroyable, pour toi cela semble naturel mais pour obtenir le même résultat, j'aurais pondu un code 4 fois plus long, moche et lent en 3 semaines! Grand merci!

Je risque d'avoir jusqu'à 600 fichiers à traiter, ça passe sans aucun souci?!
il peux être préférable de déplacer le fichier avant de l'utiliser pour éviter qu'il soit utilisé par deux exécution concurrente
Vu que ces fichiers ne prennent que extrêmement peu de place et qu'il peut être pratique de les avoir sous le coude en cas de souci pour les réinjecter dans le traitement, comment déplacer le fichier lu durant le traitement (dossier temp par exemple) et le déplacer une seconde fois dans un dossier type archive?

Oh, et puis je vais en demander surement un peu beaucoup mais est il possible de tester la table avant pour voir si une ligne avec la même date existe déjà et dans ce cas remplacer la valeur?!

Merci!
:D

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 05 oct. 2013, 01:39

une version fonctionnelle
<?php
try {
    // connexion
    $pdo = new PDO('mysql:host=localhost;dbname=josse34', 'josse34', 'josse34');
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);

    $dir = new DirectoryIterator(dirname(__FILE__) . '/tmpsfolder');
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() == 'data') {
            echo 'parse du fichier : '.$fileinfo->getFilename().'<br />';
            $tabFile = file($fileinfo->getPathname());
            preg_match('/^fic(\d+)-(\d+)-(\d+)-(\d+).data$/',$fileinfo->getFilename(),$match);
            $table = $match[1];
            $stmt = $pdo->prepare('INSERT INTO `'.$table.'` (poste,dtlog, glot) VALUES (:poste,str_to_date(:dt,\'%Y%m%d\'),:glot)');
            if (count($tabFile) > 0) {
                unset($tabFile[0]);
                $i = 0;
                foreach ($tabFile as $line) {
                    $csv = str_getcsv($line, ';');
                    $stmt->bindValue(':poste', $csv[0], PDO::PARAM_INT);
                    $stmt->bindValue(':dt', $csv[1]);
                    $stmt->bindValue(':glot', $csv[2], PDO::PARAM_INT);
                    $stmt->execute();
                    echo 'insertion de la ligne '.$i.'<br />';
                    $i++;
                }
            }
        }
    }
} catch (Exception $e) {
    echo $e->getMessage() . '<br />' . $e->getTraceAsString();
}
@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 04 oct. 2013, 11:36

Créer une table différentes par logger pourquoi mais ce n'est pas forcément utile et surtout le numéro n'est pas parlant du tous.
Mais il est vrai que tu pex tes bien lister les numéros de logger et repartir dans plusieurs tables mais côté modèle c'est moyen.
Après réflexion, c'est vraiment ce qu'il me faut, une base "dataloggers" avec diverses tables ayants pour nom les identifiants comme "34154001" (tordu peut être mais bien plus simple pour moi!) avec pour données 2 colonnes uniquement "Date" et "Valeur".
Pour le reste effectivement le code n'affiche rien ;)
Vu que c'est pour un bat y ce n'est pas trop grave.
Tu peu aussi remplacer l'affichage dans le catch par l'insertion de l'erreur dans un log.
Les erreurs ne s'affichent que pour les soucis MySQL, mais la je ne comprends pas, page blanche (donc pas d'erreur MySQL) mais rien dans la base :
Soit il ne trouve pas les fichiers avec DirectoryIterator(dirname(__FILE__) . '\tmpsfolder') pourtant le scipt se trouve dans un dossier ou il y a le dossier tmpsfolder avec les fichiers .data - PEU PROBABLE SELON MES TESTS.
Soit il ne peut insérer dans la table, et d'ailleurs j'ai essayé de supprimer la table, le script affiche toujours page blanche! Je ne comprends pas le Catch n'affiche rien!

Comment afficher toutes les erreurs (EasyPHP est réglé par défaut pour afficher toutes les erreurs) afin de résoudre le souci?

Merci!

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 04 oct. 2013, 07:03

Créer une table différentes par logger pourquoi mais ce n'est pas forcément utile et surtout le numéro n'est pas parlant du tous.
Mais il est vrai que tu pex tes bien lister les numéros de logger et repartir dans plusieurs tables mais côté modèle c'est moyen.

Pour le reste tu as presque tous bon ;)

La méthode prépare permet de precompiler la requête sur le serveur et ensuite on ne fai que l'exécuter en lui fournissant les paramètres.
L'avantage c'est un gain de performance indéniable presque l'on utilise une requête dans une boucle (comme ici).

Pour le reste effectivement le code n'affiche rien ;)
Vu que c'est pour un bat y ce n'est pas trop grave.
Tu peu aussi remplacer l'affichage dans le catch par l'insertion de l'erreur dans un log.

La méthode execute execute la requête préparée avec les info fournit par les bindValue

Dans ton cas je suppose que tu n'as pas de répertoire tmpsfolder a la racine du script (au même niveau) avec les fichier data dedans ?
L'emplacement du répertoire n'est pas important il simplement que puisse lire ce qu'il y a dedans.
La partie avec la constante __FILE__ c'est pour dit de retourner le répertoire (path complet) dans lequel se trouve le fichier courant.

@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 03 oct. 2013, 21:32

Modération :
Les "up" sont interdits sur PHPFrance.

Désolé!

Ouaou, ce code me semble excellemment propre mais bien au dessus de mes compétences !

si tu as plus d'info sur les datalogger, autre le N° de la première colonne (qui est toujours le même ?) tu peux créer une table représentant un datalogger.
par exemple
id int <= le N° de la 1ère colonne
nom
description

Effectivement, la première ligne sera toujours le même numéro, comme le nom du fichier sous cette forme "fic34154001-2013-10-01", on pourrais tout à fait se contenter de la date et de la valeur dans une table portant le nom du datalogger, en l’occurrence ici une table nommée 34154001.

Code : Tout sélectionner

$pdo = new PDO('mysql:host=localhost;dbname=labase', '', '');
Je suppose qu'il s'agit de ('mysql:host=127.0.0.1;dbname=labase', 'username', 'password')

Code : Tout sélectionner

$stmt = $pdo->prepare('insert into log () values (:poste,str_to_date(:dt,\'Ymd\')),:glot');
Dans base "labase" intégration dans table "logs"

Code : Tout sélectionner

$dir = new DirectoryIterator(dirname(__FILE__) . '/tmpsfolder');
dossier dans lequel se trouve les fichiers .DATA

Code : Tout sélectionner

if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() != 'csv') {
Type de fichier à rechercher? Dans mon cas ce n'est pas "csv" mais "data.

Rectification de ton erreur getgetPathname() en getPathname() et création de la base "labase" dans MYSQL et table "logs" avec 3 colonnes (poste/dt/glot en INT), le code suivant tourne mais laisse une page blanche sans aucun message d'erreur sans que cela n'injecte quoique ce soit dans MYSQL :

Code : Tout sélectionner

<?php try { // connexion $pdo = new PDO('mysql:host=127.0.0.1;dbname=labase', 'root', ''); $stmt = $pdo->prepare('insert into logs () values (:poste,str_to_date(:dt,\'Ymd\')),:glot'); $dir = new DirectoryIterator(dirname(__FILE__) . '/tmpsfolder'); foreach ($dir as $fileinfo) { if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() != 'data') { $tabFile = file($fileinfo->getPathname()); if (count($tabFile) > 0) { unset($tabFile[0]); foreach ($tabFile as $line) { $csv = str_getcsv($line,';'); $stmt->bindValue(':poste',$csv[0], PDO::PARAM_INT); $stmt->bindValue(':dt',$csv[1]); $stmt->bindValue(':glot',$csv[2], PDO::PARAM_INT); $stmt->execute(); } } } } } catch (Exception $e) { echo $e->getMessage() . '<br />' . $e->getTraceAsString(); } ?>
Désolé si je fais des erreurs grossières, j'éditerais le post en fonction de mes avancées!

Merci!!

Re: Parser un répertoire de fichiers DATA pour intégration M

par moogli » 03 oct. 2013, 20:43

Modération :
Les "up" sont interdits sur PHPFrance.

Si tu n'as pas obtenu de réponse, c'est (au choix) :
- que ta question est mal formulée : reformule-la différemment ;
- que personne ne connaît la réponse ici : faire un "up" ne te donnera pas davantage de résultats ;
- que la réponse demandée exige un travail important que personne ne va faire à ta place ;
- que trop peu de temps s'est écoulé depuis ton précédent message pour qu'un membre ait pu y répondre.

Merci de prendre le temps de lire les règlements.


pour le reste il y a plusieurs solutions.
si tu as plus d'info sur les datalogger, autre le N° de la première colonne (qui est toujours le même ?) tu peux créer une table représentant un datalogger.
par exemple
id int <= le N° de la 1ère colonne
nom
description

dasn tous les cas
et une table "logs" qui va contenir les logs avec une fk vers la première.
cette table comprend les 3 colonnes du fichier

au final le code peu ressembler a cela
<?php
try {
    // connexion
    $pdo = new PDO('mysql:host=localhost;dbname=labase', '', '');
    $stmt = $pdo->prepare('insert into log () values (:poste,str_to_date(:dt,\'Ymd\')),:glot');
    $dir = new DirectoryIterator(dirname(__FILE__) . '/tmpsfolder');
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot() && $fileinfo->isFile() && $fileinfo->getExtension() != 'csv') {
            $tabFile = file($fileinfo->getgetPathname());
            if (count($tabFile) > 0) {
                unset($tabFile[0]);
                foreach ($tabFile as $line) {
                    $csv = str_getcsv($line,';');
                    $stmt->bindValue(':poste',$csv[0], PDO::PARAM_INT);
                    $stmt->bindValue(':dt',$csv[1]);
                    $stmt->bindValue(':glot',$csv[2], PDO::PARAM_INT);
                    $stmt->execute();
                }
            }
        }
    }
} catch (Exception $e) {
    echo $e->getMessage() . '<br />' . $e->getTraceAsString();
}
a tester, attention au temps d’exécution.
il peux être préférable de déplacer le fichier avant de l'utiliser pour éviter qu'il soit utilisé par deux exécution concurrente ;)

@+

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 03 oct. 2013, 09:34

Salut!
Un ptit up!
Merci!!!!

Re: Parser un répertoire de fichiers DATA pour intégration M

par josse34 » 02 oct. 2013, 10:20

Bonjour et merci pour votre participation!
ton fichier c'est du csv, il y a des fonctions le parser simplement
On me conseille d'utiliser fgetcsv, qu'en pensez vous? http://php.net/manual/fr/function.fgetcsv.php

Code : Tout sélectionner

<?php if (($handle = fopen("fic34154001-2013-09-30.data", "r")) !== FALSE) { while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { print_r($data); } fclose($handle); } ?>
Cela donne :
Array ( [0] => POSTE [1] => DATE [2] => GLOT ) Array ( [0] => 34154001 [1] => 20130929 [2] => 1168 )
Comment se retrouver les données à la ligne 2, la numérotation du ARRAY n'est pas indiqué, donc si je fais print_r($data[2]); cela indique GLOT1168 !
est ce qu'il y a toujours l'entête (la 1ère ligne) ?
Il y a toujours la première ligne effectivement, mais avec preg_match('/(\d+);(\d+);(\d+)/', $line, $matches); je ne récupère que les chiffres.
quand tu décris la ligne 34154001;20130929;1168, tu veux dire que
- la table s'appel : 34154001
- la date est 20130920
- la valeur est 1168 ?

je ne vois pas bien l’intérêt d'une table avec un numéro pour nom c'est pas logique et incompréhensible.
Je ne décide pas du contenu de ce fichier, néanmoins je peux gérer son intégration, ainsi effectivement le numéro 34154001 est un numéro unique de datalogger.
J'aurais donc plusieurs Dataloggers qui vont déposer leurs données sur ce répertoire, c'est pourquoi j'ai pensé que la base serait par exemple "datalogger" et les tables de differents nom des dataloggers (numéro donc).
Après si il est préférable de tout injecter dans la même table pour des questions de rapidité de traitement et lecture, je ne suis pas contre!
pour continuer ce que Sirakawa a avancé, avec l'extension mysqli ou PDO tu va pouvoir utiliser une requête préparée pour l'insertion ce qui va te permettre d'accélérer un peu la chose.
Je suis en train d'en prendre connaissance, quelle est la plus simple, efficace et répandue des deux?
attention au temps de traitement des fichiers il ne faut pas que le cron lance deux fois le script en parallèle si tu ne prévois pas le cas si non va y avoir des doublons :)
Bonne remarque, comment s'en prémunir autrement que la suppression des fichiers après lecture (parce que sinon, les garder ne me pose pas de souci particulier.

Deja, quelles fonctions vous me recommandez pour ouvrir un répertoire et faire le traitement en lot. Vous me recommandez de traiter les fichiers un par un (j'ouvre, je traite, j'injecte SQL, je supprime), ou un traitement en une seule fois (j'ouvre les fichiers un par un, je traite les fichiers un par un, j'injecte en SQL en une seule fois, je supprime tout le repertoire)?

Merci!
[/list]