J'essaie de lire un gros fichier une ligne à la fois. J'ai trouvé une question sur Quora qui traitait du sujet, mais il me manque quelques connexions pour que tout cela s'emboîte.
var Lazy=require("lazy");
new Lazy(process.stdin)
.lines
.forEach(
function(line) {
console.log(line.toString());
}
);
process.stdin.resume();
Le peu que je voudrais comprendre, c'est comment je pourrais lire une ligne à la fois à partir d'un fichier au lieu de STDIN comme dans cet exemple.
J'ai essayé:
fs.open('./VeryBigFile.csv', 'r', '0666', Process);
function Process(err, fd) {
if (err) throw err;
// DO lazy read
}
mais ça ne marche pas. Je sais que dans un pincement je pourrais revenir à utiliser quelque chose comme PHP, mais je voudrais comprendre cela.
Je ne pense pas que l'autre réponse fonctionnerait car le fichier est beaucoup plus volumineux que le serveur sur lequel je l'exécute dispose de mémoire.
fs.readSync()
. Vous pouvez lire des octets binaires dans un tampon, mais il n'y a pas de moyen facile de traiter les caractères UTF-8 ou UTF-16 partiels sans inspecter le tampon avant de le convertir en chaînes JavaScript et de rechercher les EOL. LeBuffer()
type n'a pas un ensemble de fonctions aussi riche pour fonctionner sur ses instances que les chaînes natives, mais les chaînes natives ne peuvent pas contenir de données binaires. Il me semble que l'absence d'un moyen intégré de lire les lignes de texte à partir de descripteurs de fichiers arbitraires est une véritable lacune dans node.js.if (line.length==1 && line[0] == 48) special(line);
node
les documents de l'API github.com/nodejs/node/pull/4609Réponses:
Depuis Node.js v0.12 et à partir de Node.js v4.0.0, il existe un module de base readline stable . Voici la manière la plus simple de lire des lignes d'un fichier, sans aucun module externe:
Ou bien:
La dernière ligne est lue correctement (à partir de Node v0.12 ou ultérieure), même s'il n'y a pas de final
\n
.MISE À JOUR : cet exemple a été ajouté à la documentation officielle de l'API de Node .
la source
rl.on('close', cb)
Pour une opération aussi simple, il ne devrait pas y avoir de dépendance vis-à-vis des modules tiers. Allez-y doucement.
la source
line
événements ne surviennent qu'après avoir frappé\n
, c'est-à-dire que toutes les alternatives sont manquées (voir unicode.org/reports/tr18/#Line_Boundaries ). # 2, les données après la dernière\n
sont silencieusement ignorées (voir stackoverflow.com/questions/18450197/… ). j'appellerais cette solution dangereuse car elle fonctionne pour 99% de tous les fichiers et pour 99% des données mais échoue silencieusement pour le reste. chaque fois quefs.writeFileSync( path, lines.join('\n'))
vous avez écrit un fichier qui ne sera lu qu'en partie par la solution ci-dessus.readline
package se comporte de manière vraiment bizarre pour un programmeur Unix / Linux expérimenté.rd.on("close", ..);
peut être utilisé comme rappel (se produit lorsque toutes les lignes sont lues)Vous n'avez pas besoin
open
du fichier, mais à la place, vous devez créer un fichierReadStream
.fs.createReadStream
Passez ensuite ce flux à
Lazy
la source
new lazy(fs.createReadStream('...')).lines.forEach(function(l) { /* ... */ }).join(function() { /* Done */ })
new lazy(...).lines.forEach(...).on('end', function() {...})
.on('end'...
après.forEach(...)
, alors qu'en fait tout s'est comporté comme prévu quand j'ai lié l'événement en premier .il y a un très joli module pour lire un fichier ligne par ligne, ça s'appelle lecteur de ligne
avec elle, vous écrivez simplement:
vous pouvez même itérer le fichier avec une interface "style java", si vous avez besoin de plus de contrôle:
la source
process/stdin
). Au moins, si c'est possible, ce n'est certainement pas évident en lisant le code et en le tentant.readline
module principal .function(reader)
etfunction(line)
devrait être:function(err,reader)
etfunction(err,line)
.line-reader
lit le fichier de manière asynchrone. L'alternative synchrone estline-reader-sync
la source
Mise à jour en 2019
Un exemple impressionnant est déjà publié sur la documentation officielle de Nodejs. ici
Cela nécessite que le dernier Nodejs soit installé sur votre machine. > 11,4
la source
await
s entre l'createInterface()
appel et le début de lafor await
boucle, vous perdrez mystérieusement des lignes depuis le début du fichier.createInterface()
commence immédiatement à émettre des lignes en arrière-plan, et l'itérateur asynchrone implicitement créé avecconst line of rl
ne peut pas commencer à écouter ces lignes jusqu'à ce qu'il soit créé.Ancien sujet, mais cela fonctionne:
Facile. Pas besoin de module externe.
la source
readline is not defined
oufs is not defined
, ajoutezvar readline = require('readline');
etvar fs = require('fs');
pour que cela fonctionne. Sinon, doux, doux. Merci.Vous pouvez toujours rouler votre propre lecteur de ligne. Je n'ai pas encore testé cet extrait, mais il divise correctement le flux entrant de morceaux en lignes sans le "\ n" de fin
J'ai trouvé cela lorsque je travaillais sur un script d'analyse de journal rapide qui devait accumuler des données pendant l'analyse de journal et je pensais que ce serait bien d'essayer de le faire en utilisant js et node au lieu d'utiliser perl ou bash.
Quoi qu'il en soit, je pense que les petits scripts nodejs devraient être autonomes et ne pas s'appuyer sur des modules tiers.Ainsi, après avoir lu toutes les réponses à cette question, chacun utilisant différents modules pour gérer l'analyse de ligne, une solution native 13 SLOC nodejs pourrait être intéressante.
la source
stdin
... à moins que je manque quelque chose.ReadStream
avecfs.createReadStream('./myBigFile.csv')
et l'utiliser au lieu destdin
readline
module principal .Avec le module porteur :
la source
var inStream = fs.createReadStream('input.txt', {flags:'r'});
Mais votre syntaxe est plus propre que la méthode documentée d'utilisation de .on ():carrier.carry(inStream).on('line', function(line) { ...
\r\n
que les\n
fins de ligne. Si vous avez besoin de traiter des fichiers de test de style MacOS antérieurs à OS X, ils ont utilisé\r
et l'opérateur ne gère pas cela. Étonnamment, il existe encore de tels fichiers dans la nature. Vous devrez peut-être également gérer explicitement la nomenclature Unicode (marque d'ordre des octets), elle est utilisée au début des fichiers texte dans la sphère d'influence MS Windows.readline
module principal .Je me suis retrouvé avec une fuite de mémoire massive et massive en utilisant Lazy pour lire ligne par ligne lorsque j'essayais de traiter ces lignes et de les écrire dans un autre flux en raison de la façon dont drain / pause / resume dans le nœud fonctionne (voir: http: // elegcode .com / 2011/04/06 / prendre-pas-de-bébé-avec-noeud-js-pomper-les-données-entre-flux / (j'adore ce mec en passant)). Je n'ai pas regardé assez attentivement Lazy pour comprendre exactement pourquoi, mais je n'ai pas pu mettre en pause mon flux de lecture pour permettre un drain sans quitter Lazy.
J'ai écrit le code pour traiter des fichiers csv massifs en documents xml, vous pouvez voir le code ici: https://github.com/j03m/node-csv2xml
Si vous exécutez les révisions précédentes avec la ligne Lazy, cela fuit. La dernière révision ne fuit pas du tout et vous pouvez probablement l'utiliser comme base pour un lecteur / processeur. Bien que j'aie des trucs personnalisés là-dedans.
Edit: Je suppose que je devrais également noter que mon code avec Lazy a bien fonctionné jusqu'à ce que je me retrouve à écrire des fragments xml suffisamment grands qui drainent / s'arrêtent / reprennent à cause d'une nécessité. Pour les petits morceaux, c'était bien.
la source
readline
module principal .Éditer:
Utilisez un flux de transformation .
Avec un BufferedReader, vous pouvez lire des lignes.
la source
readline
module principal .Depuis la publication de ma réponse d'origine, j'ai découvert que split est un module de nœud très facile à utiliser pour la lecture de ligne dans un fichier; Qui accepte également des paramètres facultatifs.
N'ont pas été testés sur de très gros fichiers. Faites-nous savoir si vous le faites.
la source
J'étais frustré par l'absence d'une solution complète pour cela, alors j'ai mis en place ma propre tentative ( git / npm ). Liste des fonctionnalités copiées-collées:
NIH? Tu décides :-)
la source
la source
data
appel àstream.on("data")
pourrait jamais commencer ou se terminer avec seulement une partie d'un caractère UTF-8 multi-octets tel que celuiა
qui estU+10D0
composé des trois octetse1
83
90
readline
module principal .Je voulais aborder ce même problème, essentiellement ce que serait en Perl:
Mon cas d'utilisation était juste un script autonome, pas un serveur, donc synchrone était bien. Ce sont mes critères:
C'est un projet pour moi d'avoir une idée du code de type de script de bas niveau dans node.js et de décider de sa viabilité en remplacement d'autres langages de script comme Perl.
Après un effort surprenant et quelques faux départs, voici le code que j'ai trouvé. C'est assez rapide mais moins trivial que ce à quoi je m'attendais: (forkez-le sur GitHub)
Il pourrait probablement être nettoyé davantage, c'était le résultat d'essais et d'erreurs.
la source
Dans la plupart des cas, cela devrait suffire:
la source
Lecteur de ligne basé sur générateur: https://github.com/neurosnap/gen-readlines
la source
Si vous voulez lire un fichier ligne par ligne et l'écrire dans un autre:
la source
J'ai eu le même problème et j'ai trouvé la solution ci-dessus qui ressemble à d'autres, mais est aSync et peut lire des fichiers volumineux très rapidement
Espère que cela aide
la source
J'ai un petit module qui le fait bien et qui est utilisé par un certain nombre d'autres projets npm readline Notez que dans le nœud v10, il y a un module natif readline, j'ai donc republié mon module en ligne par ligne https://www.npmjs.com/package/ ligne par ligne
si vous ne souhaitez pas utiliser le module, la fonction est très simple:
la source
Une autre solution consiste à exécuter la logique via l'exécuteur séquentiel nsynjs . Il lit les fichiers ligne par ligne à l'aide du module de lecture en ligne du nœud, et il n'utilise pas de promesses ou de récursivité, donc n'échouera pas sur les fichiers volumineux. Voici à quoi ressemblera le code:
Le code ci-dessus est basé sur cet exemple: https://github.com/amaksr/nsynjs/blob/master/examples/node-readline/index.js
la source
Deux questions que nous devons nous poser lors de telles opérations sont:
Des solutions comme
require('fs').readFileSync()
charge tout le fichier en mémoire. Cela signifie que la quantité de mémoire requise pour effectuer des opérations sera presque équivalente à la taille du fichier. Nous devons les éviter pour tout ce qui dépasse50mbs
Nous pouvons facilement suivre la quantité de mémoire utilisée par une fonction en plaçant ces lignes de code après l'invocation de la fonction:
En ce moment , la meilleure façon de lire certaines lignes à partir d' un fichier volumineux utilise du nœud de readline . La documentation a des exemples étonnants .
Bien que nous n'ayons pas besoin d'un module tiers pour le faire. Mais, si vous écrivez un code d'entreprise, vous devez gérer de nombreux cas marginaux. J'ai dû écrire un module très léger appelé Apick File Storage pour gérer tous ces cas extrêmes.
Module de stockage de fichiers Apick: https://www.npmjs.com/package/apickfs Documentation: https://github.com/apickjs/apickFS#readme
Exemple de fichier: https://1drv.ms/t/s!AtkMCsWInsSZiGptXYAFjalXOpUx
Exemple: installer le module
Cette méthode a été testée avec succès jusqu'à 4 Go de fichiers denses.
big.text est un fichier texte dense avec 163 845 lignes et est de 124 Mo. Le script pour lire 10 lignes différentes de ce fichier utilise environ 4,63 Mo de mémoire seulement. Et il analyse gratuitement le JSON valide en objets ou tableaux. 🥳 Génial !!
Nous pouvons lire une seule ligne du fichier ou des centaines de lignes du fichier avec très peu de consommation de mémoire.
la source
j'utilise ceci:
utilisez cette fonction sur un flux et écoutez les événements de ligne qui seront émis.
gr-
la source
Bien que vous deviez probablement utiliser le
readline
module comme le suggère la réponse du haut, ilreadline
semble être orienté vers les interfaces de ligne de commande plutôt que vers la lecture de ligne. Il est également un peu plus opaque en ce qui concerne la mise en mémoire tampon. (Quiconque a besoin d'un lecteur orienté ligne de streaming voudra probablement modifier la taille des tampons). Le module readline fait ~ 1000 lignes alors que celui-ci, avec statistiques et tests, est de 34.Voici une version encore plus courte, sans les statistiques, à 19 lignes:
la source
la source
J'enveloppe toute la logique du traitement de ligne quotidien comme un module npm: kit de ligne https://www.npmjs.com/package/line-kit
la source
J'utilise ci-dessous le code des lignes de lecture après avoir vérifié que ce n'est pas un répertoire et qu'il n'est pas inclus dans la liste des fichiers n'a pas besoin d'être vérifié.
la source
J'ai regardé toutes les réponses ci-dessus, toutes utilisent une bibliothèque tierce pour le résoudre. C'est une solution simple dans l'API de Node. par exemple
la source