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

Scripts/Batch Discussion :

Manipulation de gros fichier CSV [PowerShell]


Sujet :

Scripts/Batch

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut Manipulation de gros fichier CSV
    Bonjour.

    Je souhaite traiter un fichier qui est au format CSV et très volumineux (20 millions d'enregistrements, 48 champs, 4 Go).
    Il faudrait :
    - Supprimer des "colonnes".
    - Remplacer des chaines de caractères.
    - Enlever les quotes si besoin et remplacer les "," par des ";"
    - Dans l'idéal, formater un champ numérique (afficher le nombre sur 9 caractères avec des zéros devant : '27' => '000000027')

    J'ai essayé avec Python, le traitement me prend moins de 5 minutes
    Mais c'est pour le travail, et au travail je n'ai (normalement) pas accès à Python
    En fait, je n'ai accès qu'à Powershell (et JS, mais j'ai des légers doutes pour un traitement de ce genre)

    J'ai trouvé un exemple sur le blog de Balladelli. Après adaptation j'ai donc cette commande qui conserve uniquement les champs souhaités :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Import-Csv MonGrosFichier.csv | Select champ1, champ2, champ5, champ6, champ24, champ42| Export-Csv MonPetitFichier.csv –NTI -Delimiter ';'
    Il me reste ensuite à traiter les chaines de caractères, avec des .replace() (plus rapides que _replace, si j'ai bien suivi) sur un fichier plus petit (2 Go) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (Get-Content $csvfile) | Foreach-Object {$_.replace('"', '').replace('true', '1').replace('false',0)}|Out-File $csvfile
    Problèmes :
    - la première étape me prend énormément de temps : 2 heures (calculé avec Measure-Command {})
    - la deuxième étape est tellement gourmande ( 6 Go de RAM pour traiter un fichier qui en fait 2) que j'ai fini par tuer le processus
    A titre indicatif, mon script Python me prend 5 minutes pour tout faire

    Il y a moyen d'optimiser le traitement (éventuellement en passant par Get-Content pour la première étape, ou en faisant une lecture ligne à ligne) ? Ou de forcer l'utilisation de plusieurs threads/plus de mémoire ?
    Ou je dois considérer que PS ne pourra pas mieux faire ?


    PS :
    Quand je parle de Python, ce n'est pas pour dire que PS est mauvais c'est juste pour avoir un point de comparaison : l'ordinateur est capable de faire le traitement demandé en 5 minutes. S'il n'y arrive pas, c'est soit que PS n'est pas adapté pour ce genre de traitement, soit que les commandes ne sont pas bonnes...

  2. #2
    Invité de passage
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Janvier 2019
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Janvier 2019
    Messages : 1
    Par défaut Comment enlever l’entête du fichier csv sans faire get-content
    Bonjour,
    Je suis en face d'une problématique d'optimisation lors de la copie d'un fichier d'un dossier vers un autre.
    je m'explique :
    je reçois un fichier csv avec l'entête, et je souhaite enlever cet entête sauf que quand je reçois de gros fichiers (de l'ordre de 1 million de lignes), le traitement prend un temps fou!!!
    ci-dessous le script que j'ai fait et qui marche très bien pour des fichiers non volumineux

    Code PowerShell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $MyFile = Get-Content $pathTmp\$file
    $MyFile[1..($MyFile.length-1)] > $pathTmp\$file
    $MyFile1 = Get-Content $pathTmp\$file
    $MyFile1 | Out-File -Encoding "Default" $pathTmp\$Newname

    ce script ouvre le fichier(get-content) avec entête $file, puis enlève l'entête, le stocke dans $MyFile1 et le relit encore une fois et l'enregistrer pour le déplacer!!!
    cette manip de lecture pour enlever l'entête consomme beaucoup de temps.
    Ma demande est comment réécrire ce script de façon à enlever l'entête sans faire des get-content ?

    Merci pour votre aide

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Conclusion (temporaire ?) :
    En cherchant je suis tombé sur cet article...

    Au final, j'utilise
    Code powershell : 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
    $reader = [System.IO.File]::OpenText($entree)
    $stream = [System.IO.StreamWriter] $sortie
    try {
        for() {
            $line = $reader.ReadLine()
            $cpt = $cpt + 1 
    		if ($line -eq $null) { break }
    		$tab = $line.split(",")
    		$ligne = $tab[0],$tab[1],$tab[4],$tab[5].Replace("true",1).Replace("false",0),$tab[23],$tab[41] -join ";"
    		$stream.WriteLine($ligne)
        }
    }
    finally {
        $reader.Close()
    	$stream.close()
    	$stream2.close()
    }
    Je suis tombé à 27 minutes pour un fichier de 27 M de lignes...c'est long, mais pour le moment ça ira (je le passerai une fois par mois, normalement)...

    Il me reste un problème : il y a des lignes pour lesquelles le champ 6 (celui avec "true/false") n'est pas renseigné.
    Dans ce cas, le script plante parce que j'essaye de faire un Replace sur une variable null
    J'ai contourné à la barbare (ce qui me permet d'avoir une valeur par défaut, c'est déjà ça) :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    $tab[5]+"0".Replace("true0",1).Replace("false0",0)
    Mais il doit y avoir mieux

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 73
    Par défaut
    Bonjour.

    Je te conseille d'ouvrir un nouveau sujet pour exposer ton problème, tu auras plus de chances d'avoir une réponse - et moi aussi

    En attendant tu peux essayer :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    Get-Content .\$entree| Select-Object -Skip 1 | Set-Content .\$sortie

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

Discussions similaires

  1. Très gros fichier CSV
    Par kidathom dans le forum Débuter
    Réponses: 6
    Dernier message: 29/04/2008, 13h00
  2. Lecture et manipulation de "gros" fichiers.
    Par ::Fistons dans le forum Entrée/Sortie
    Réponses: 18
    Dernier message: 17/03/2008, 11h37
  3. Manipuler un gros fichier texte
    Par bremer dans le forum Langage
    Réponses: 14
    Dernier message: 27/02/2008, 19h16
  4. [CSV] Traitement d'un gros fichier CSV
    Par Adrinou dans le forum Langage
    Réponses: 6
    Dernier message: 09/10/2007, 12h40
  5. [MySQL] Traitement de gros fichier CSV
    Par oceanbigone dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 03/07/2007, 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