J'ai des fichiers CSV qui ont plusieurs colonnes triés. Par exemple, je pourrais avoir des lignes comme ceci: Je voudrais diviser le fichier en fonction de la 3e colonne, par exemple. Mettez des entrées PCXS et PCP dans leurs propres fichiers appelés plXs.csv et pcp.csv. Étant donné que le fichier est prédéfini, toutes les entrées PLXS sont avant les entrées PCP et ainsi de suite. P> Je finis généralement à faire des choses comme ceci en C ++ car c'est la langue que je connais le mieux, Mais dans ce cas, mon fichier CSV d'entrée est plusieurs gigaoctets et trop volumineux pour charger en mémoire en C ++. P> Quelqu'un peut-il montrer comment cela peut être accompli? Les solutions PERL / PYTHON / PHP / BASH sont toutes d'accord, ils doivent simplement être capables de gérer le fichier énorme sans utilisation excessive de mémoire. P> P>
6 Réponses :
C ++ est bien si vous le savez mieux. Pourquoi voudriez-vous essayer de charger tout ce qui est en mémoire? p>
Étant donné que la sortie dépend de la colonne en cours de lecture, vous pouvez facilement stocker des tampons pour les fichiers de sortie et utiliser l'enregistrement dans le fichier approprié au fur et à mesure que vous traitez, car vous allez conserver l'empreinte de mémoire relativement petite. p>
Je fais cela (même en Java) pour prendre des extraits massifs d'une base de données. Les enregistrements sont enfoncés dans un flux de tampon de fichier et tout ce qui est de la mémoire est nettoyé afin que l'empreinte du programme ne pousse jamais au-delà de ce qu'elle commence initialement à. p>
voler par le siège de mon pantalon pseudo-code: p>
poursuit essentiellement ce traitement jusqu'à la fin du fichier. p>
Depuis que nous ne stockons jamais plus que des pointeurs vers les ruisseaux et que nous rinçons dès que nous écrivons dans les ruisseaux, nous n'avons jamais rien de résident dans la mémoire de l'application, autre que d'un enregistrement du fichier d'entrée. Ainsi, l'empreinte est gagnée. p>
+1: C ++ n'est pas le problème. Chargement de l'ensemble du fichier en mémoire est le problème.
Une solution alternative serait de charger le CSV dans un SOLR Index, puis générez le CSV fichiers basés sur vos critères de recherche personnalisés. p>
Voici un HOWTO de base: P>
Créer un rapport et télécharger sur serveur pour le téléchargement < / a> p>
Voici une ancienne école One Dower pour vous (remplacez simplement le >> code> avec
> code> pour tronquer les fichiers de sortie chaque exécution):
HDR=$(head -1 input.csv); for fn in $(tail -n+2 input.csv | cut -f3 -d, | sort -u); do echo $HDR > $fn.csv; done
c'est génial :) Ce serait encore mieux si nous pouvions conserver les en-têtes
Il n'y avait pas d'en-têtes dans l'original. Peut-être que vous pouvez poser une question différente?
Cela m'a aidé - mais d'améliorer - l'exemple d'en-têtes peut être simplifié en utilisant nr == 1 {hdr = 0 $; Suivant} code> Ensuite, vous n'avez pas besoin de vérifier NR sur les modèles suivants, car vous ne pouvez pas accéder à ces modèles et ne pas être NR> 1 en raison de la règle de commande d'AWK. De l'homme Page:
Chaque modèle du programme doit ensuite être évalué dans l'ordre d'occurrence et l'action associée à chaque modèle correspondant à l'enregistrement actuel exécuté. Code>
Aussi une amélioration mineure - le modèle de nom de fichier {fn = 3 $ ".csv"} code> doit se produire après le modèle NR == 1, car il n'est utilisé que par des motifs qui suivent.
Merci pour les commentaires, @Phil. Je ne crois pas qu'un profileur montrerait une modification ou une amélioration après vos suggestions et je crois que les intentions explicites appuyées par les constructions de langue AWK code> AWK CODE> (que vous avez utilement incluse et que je me sens aussi très clair) . 1. Aucune modification logique en ajoutant
Suivant code>. Supprimer des directives explicites AWK qui définissent intentionnellement le but d'un bloc de code constituerait un anti-motif de la citation que vous avez fournie. 2. Réorganiser les modèles que vous faites référence dans le programme change Aucun plan d'exécution de code, alors n'hésitez pas à modifier votre copie!
Bonjour Sean, profilant Ceci utilisant --Profile montre que votre version teste le motif et l'exécute - Création du nom de fichier N + 1 fois, lorsque la mine appelle N fois. Notez que, comme il n'y a pas de modèle à tester dans ma version, chaque "test" doit donc être plus rapide. Le résultat de l'utilisation de Suivant code> est que les modèles suivants sont testés n Times, alors que sans
Suivant code> N + 1 tests se produisent. Évidemment, le nombre d'exécutions du corps de motif restent les mêmes, cependant que j'ai simplifié chaque motif, chaque test nécessite moins de travail dans le cas du tableau P et aucun test n'est requis pour écrire la ligne de sortie.
Bien sûr, j'accepte que certains susceptibles de ressentir la perte de la clarté de s'appuyer sur les règles de commande des schémas, ne valent pas ces échanges assez modestes - cela dépend de la taille des données d'entrée et de la complexité du traitement par ligne. Je trouve personnellement qu'il est moins encombré de retirer les tests de motif quand ils ne sont pas nécessaires - mais je vis cela à partir d'un point de vue du manuel, mon script est légèrement et manifestement en profilant, plus efficace.
J'apprécie votre pédantisme et votre persévérance, @Phil. Je suis également impressionné par ce que vous envisagez de «accélérations assez modestes». J'attends avec impatience ce que vous pouvez faire avec la mise en œuvre de la réponse acceptée ici, en C ++!
LOL - Touche ... bien ce serait certainement une question différente! Mais mon pédantisme découle de penser à la manière dont le C sous-jacent fonctionnerait. Un awk bien écrit ne testerait sûrement pas un manque de prédicat des motifs?
Si les trois premières colonnes de votre fichier n'ont pas cité des virgules, une simple doublure est la suivante:
cat file | perl -e 'while(<>){@a=split(/,/,$_,4);$key=$a[2];open($f{$key},">$key.csv") unless $f{$key};print {$f{$key}} $_;} for $key (keys %f) {close $f{$key}}'
En fait, je remarque juste que cela est essentiellement la même réponse que celle de Sean Summers ci-dessous.
a,b,c,d,e,f,g,h,i,j,k,l 19980102,,PLXS,10032,Q,A,,,15.12500,15.00000,15.12500,2 19980105,,PLXS,10032,Q,A,,,14.93750,14.75000,14.93750,2 19980106,,PLXS,10032,Q,A,,,14.56250,14.56250,14.87500,2
S'il n'y a pas de ligne d'en-tête dans le fichier d'entrée s'il y a une ligne d'en-tête qui doit être transmise sur les fichiers écartés p>
Avez-vous parcouru du tout? Plusieurs questions connexes sur ce site dans toutes les langues ci-dessus et plus encore. Vous pouvez rechercher:
Site: Stackoverflow.com CSV Split par valeur code> ou une autre variante. bonne chance