Lire un fichier ligne par ligne, dans node.js?
Je suis en train de lire un gros fichier, une ligne à la fois. J'ai trouvé une question sur Quora qui traitent de ce sujet mais il me manque certaines connexions de rendre l'ensemble de l'ajustement ensemble.
var Lazy=require("lazy");
new Lazy(process.stdin)
.lines
.forEach(
function(line) {
console.log(line.toString());
}
);
process.stdin.resume();
Le peu que j'aimerais savoir 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 cela ne fonctionne pas. Je sais que dans une pincée je pourrais tomber en arrière à l'aide de quelque chose comme PHP, mais je voudrais comprendre.
Je ne pense pas que l'autre réponse pourrait fonctionner comme le fichier est beaucoup plus grande que le serveur, je suis en cours d'exécution sur a de la mémoire pour.
- Cela s'avère très difficile à l'aide de bas-niveau
fs.readSync()
. Vous pouvez lire binaires octets dans le buffer, mais il n'y a pas de moyen facile de traiter avec partielle UTF-8 ou UTF-16 caractères sans l'inspecter la mémoire tampon avant de la traduire pour les chaînes de caractères JavaScript et de numérisation pour EOLs. LeBuffer()
type n'est pas aussi riche ensemble de fonctions de fonctionner sur ses instances en tant que natif des chaînes, mais natif chaînes ne peuvent pas contenir des données binaires. Il me semble que, faute d'un moyen intégré pour lire des lignes de texte de l'arbitraire descripteurs est une vraie lacune dans la node.js. - Les lignes vides lue par cette méthode se transforme en une ligne avec un seul 0 (caractère réel de code pour 0) en eux. J'ai eu de hack cette ligne là:
if (line.length==1 && line[0] == 48) special(line);
- On peut aussi utiliser la "ligne par ligne" package qui fait le travail parfaitement.
- Veuillez mettre à jour la question de dire que la solution est d'utiliser un le flux de transformation
- Vous souhaitez mettre à jour la question avec le built-in moyen de lire les lignes d'un fichier comme de Nœud v0.12.
- si vous le souhaitez, vous pouvez rajouter à la liste: votre exemple a atterri légèrement modifiée dans
node
's de l'API docs github.com/nodejs/node/pull/4609 - C'est assez cool! Merci pour le faire 🙂
- bienvenue. 🙂 Ce message a été vraiment utile, alors...
- Voir aussi Quora: quora.com/...
Vous devez vous connecter pour publier un commentaire.
Depuis Node.js v0.12 et comme de Node.js v4.0.0, il est stable readline module de base. Voici la façon la plus simple de lire les lignes d'un fichier, sans modules externes:
La dernière ligne est lue correctement (comme de Nœud v0.12 ou plus tard), même si il n'y a pas de finale
\n
.Mise à JOUR: cet exemple a été ajouté à un Nœud de l'API documentation officielle.
.createInterface({ input: require('fs').createReadStream('file.in'), terminal: false });
? Dan ou je serai heureux de mise à jour - peut-être avec un /* commentaire */ expliquant pourquoi il doit être làterminal: false
. Pouvez-vous expliquer pourquoi il aurait besoin d'être là?terminal :false
comme @glasspill a mentionné. J'ai moi-même besoin lors de l'exécution d'un script à partir d'un fichier à la fois Node.js 0.12.7 et Node.js 4.0.0, parce que sinon, je reçois un message d'erreur concernantisTTY
est indéfini. Lereadline
paquet est spécifiquement conçu pour s'exécuter dans le terminal, donc, dans mon code j'ai besoin de le configurer de sorte qu'il peut être utilisé à partir d'un script.rl.on('close', cb)
var count = 0;
au top, avec uncount++;
en haut de laon('line')
gestionnaire @Ryan utilisation lineReader.pause() en haut de laon('line')
gestionnaire et l'utilisation lineReader.resume() lorsque vous êtes prêt à continuer.lineReader.pause(); lineReader.close();
cela fonctionne pour vous? Je n'ai pas encore besoin d'arrêter le traitement...readline
, mais j'ai fini par utiliserline-by-line
- here il est.if
déclaration autour de laconsole.log
déclaration. Si le programme de cette condition, est-il un moyen de lire ligne par ligne à partir de là?Une telle opération simple, il ne devrait pas y avoir de dépendance des modules tiers. Aller simple.
line
événements viennent seulement après avoir atteint\n
, c'est à dire, toutes les alternatives sont manqués (voir unicode.org/reports/tr18/#Line_Boundaries). #2, les données après la dernière\n
silencieusement ignoré (voir stackoverflow.com/questions/18450197/...). je dirais que cette solution dangereux cause, il travaille pour 99% de tous les dossiers et pour 99% des données, mais échoue silencieusement pour le reste. chaque fois que vous faitesfs.writeFileSync( path, lines.join('\n'))
vous avez écrit un fichier qui ne sera que partiellement lu par la solution ci-dessus.readline
paquet se comporte vraiment bizarres façons expérimenté Unix/Linux programmeur.rd.on("close", ..);
peut être utilisé comme un rappel (atteint son apogée lorsque toutes les lignes sont lues)Vous n'avez pas à
open
le fichier, mais au lieu de cela, vous devez créer unReadStream
.fs.createReadStream
Puis passer que les flux de
Lazy
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 lorsque j'ai lié l'événement premier.il y a une très belle module pour lire un fichier ligne par ligne, il est appelé ligne-lecteur de
avec il vous suffit juste d'écrire:
vous pouvez même effectuer une itération le fichier avec un "java" de style de l'interface, si vous avez besoin de plus de contrôle:
process/stdin
). Au moins, s'il le peut, ce n'est certainement pas évident à partir de la lecture du code et tenter de l'appliquer.readline
de base du module.function(reader)
etfunction(line)
devrait être:function(err,reader)
etfunction(err,line)
.line-reader
lit le fichier en mode asynchrone. La machine synchrone alternative à cela estline-reader-sync
Vieux sujet, mais cela fonctionne:
Simple. Pas besoin d'un module externe.
readline is not defined
oufs is not defined
, ajoutervar readline = require('readline');
etvar fs = require('fs');
pour obtenir que cela fonctionne. Sinon, doux, doux code. Merci.Vous pouvez toujours passer votre propre ligne de lecteur. J'ai pas comparé cet extrait, mais il correctement divise le flux entrant de morceaux en lignes sans le caractère nul '\n'
Je suis venu avec cette lorsque vous travaillez sur un rapide journal de l'analyse de script que nécessaire pour accumuler des données pendant le journal d'analyse et j'ai pensé qu'il serait sympa d'essayer de faire cela à l'aide de js et nœud au lieu de l'aide de perl, bash.
De toute façon, j'ai le sentiment que les petites nodejs le script doit être autonome et ne pas dépendre des modules tiers, donc après la lecture de toutes les réponses à cette question, chacun à l'aide de divers modules pour gérer la ligne de l'analyse, une 13 SLOC natif de nodejs solution pourrait être d'intérêt .
stdin
... sauf si je suis absent somethign.ReadStream
avecfs.createReadStream('./myBigFile.csv')
et l'utiliser à la place destdin
readline
de base du module.last
être unBuffer
, utilisezlast.indexOf('\n)
etlast.slice()
au lieu desplit()
. La chose cool à propos de l'UTF-8, c'est que seuls les octets qui peuvent être rendues par des caractères ASCII sera le 8e bit mis à 0. La numérisation de la mémoire tampon pour 10 ne jamais correspondre à des retours à la ligne et de ne jamais partie d'un caractère multi-octets. Mais si vous avez besoin de plus que de l'UTF-8, un décodage généralisé solution serait le mieux.Avec le module de support de:
var inStream = fs.createReadStream('input.txt', {flags:'r'});
Mais votre syntaxe est plus propre que la méthode documentée de l'aide .sur():carrier.carry(inStream).on('line', function(line) { ...
\r\n
et\n
les fins de ligne. Si jamais vous avez besoin de traiter avec MacOS style fichiers de test avant OS X, ils ont utilisé\r
et le transporteur ne gère pas cela. Étonnamment, il y a encore de tels fichiers flottant sur à l'état sauvage. Vous pourriez aussi avoir besoin de gérer l'Unicode BOM (byte order mark) explicitement, ce est utilisé au début des fichiers texte dans le MS Windows sphère d'influence.readline
de base du module.Je me suis retrouvé avec un énorme, énorme fuite de mémoire à l'aide de Paresseux pour lire ligne par ligne en essayant de les traiter ensuite de ces lignes et de les écrire dans un autre flux en raison de la manière de vidange/mettre en pause/reprendre dans le fonctionnement du nœud (voir: http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/ (j'adore ce mec d'ailleurs)). Je n'ai pas regardé d'assez près Paresseux pour comprendre exactement pourquoi, mais je ne pouvais pas interrompre ma lecture de flux afin de permettre une vidange sans Paresseux de quitter.
J'ai écrit le code pour traiter de très gros fichiers csv en xml docs, vous pouvez voir le code ici: https://github.com/j03m/node-csv2xml
Si vous exécutez les révisions précédentes avec Lazy ligne il ya des fuites. La dernière révision n'y a pas de fuite du tout, et vous pouvez probablement utiliser comme base pour un lecteur/processeur. Si j'ai quelques trucs là.
Edit: je suppose que je dois aussi préciser que mon code avec Lazy a bien fonctionné jusqu'à ce que j'ai trouvé moi-même écrit assez gros fragments xml qui drainent/mettre en pause/reprendre, car une nécessité. Pour de plus petits morceaux, il était beau.
readline
de base du module.Edit:
Utiliser un le flux de transformation.
Avec un BufferedReader vous pouvez lire les lignes.
readline
de base du module.Puisque l'envoi de ma réponse, j'ai trouvé que split est un très facile à utiliser nœud module de lecture de ligne dans un fichier; Qui accepte des paramètres facultatifs.
Ne l'ai pas testé sur de très gros fichiers. Laissez-nous savoir si vous le faites.
J'ai été frustré par l'absence d'une solution globale pour cela, j'ai donc monté ma propre tentative (git /npm). Copie-collé de la liste des caractéristiques:
NIH? De vous décider 🙂
data
dans l'appel àstream.on("data")
peut jamais commencer ou se terminer avec la deuxième partie de la séquence multi-octets de caractères UTF-8 commeა
qui estU+10D0
, composé de trois octetse1
83
90
readline
de base du module..slice()
est seulement autour des caractères de saut de ligne qui sont en ASCII, il n'y a pas de danger de la division d'un char en UTF-8. Mais il y a dans d'autres codages UTF-16. Dans votre exemple, UTF-8 valide d'entrée ne serait jamais0xe1830a90
parce que0x0a
jamais peut être une partie d'un caractère multi-octets. En fait, George a bien répondu à votre question, même si vous prétendez qu'il n'a pas.Dans la plupart des cas, cela devrait être suffisant:
Mise à jour en 2019
Un impressionnant exemple est déjà posté sur officiel Nodejs documentation. ici
Cela nécessite la dernière Nodejs est installé sur votre machine. >11.4
Je voulais m'attaquer à ce même problème, fondamentalement, ce qui en Perl serait:
Mon cas d'utilisation était juste un script autonome, pas un serveur, de manière synchrone était très bien. C'étaient mes critères:
C'est un projet pour moi d'obtenir une sensation pour le faible niveau de script de type code node.js et décider de la manière viable c'est comme un remplacement pour d'autres langages de script comme Perl.
Après une quantité surprenante de l'effort et un couple de faux départs, c'est le code que j'ai trouvé. C'est assez rapide mais moins trivial que je ne l'ai prévu: (fork sur GitHub)
Il pourrait probablement être nettoyés en outre, il a été le résultat d'essai et d'erreur.
Générateur de ligne de lecteur: https://github.com/neurosnap/gen-readlines
Si vous voulez lire un fichier ligne par ligne et par écrit dans un autre:
J'ai eu le même problème et est venu avec la solution ci-dessus
regarde similaires pour les autres, mais est asynchrone et peut lire des fichiers volumineux très rapidement
Espère que cette aide
J'ai un petit module qui le fait bien et est utilisé par un bon nombre d'autres projets npm readline Note thay nœud v10 il est originaire readline module, donc j'ai réédité mon module linebyline https://www.npmjs.com/package/linebyline
si vous ne voulez pas utiliser le module de la fonction est très simple:
Une autre solution consiste à exécuter la logique séquentielle via exécuteur nsynjs. Il lit le fichier ligne par ligne à l'aide du nœud readline module, et il n'utilise pas de promesses ou de la récursivité, donc ne pas aller à l'échec sur de gros fichiers. Voici comment le code ressemble à ceci:
Code ci-dessus est basée sur ce exampe: https://github.com/amaksr/nsynjs/blob/master/examples/node-readline/index.js
j'utilise ceci:
utiliser cette fonction sur un ruisseau et d'écouter les événements de la ligne qui sera émise.
gr-
Alors vous devriez probablement utiliser la
readline
module de la réponse sommet suggère,readline
semble être orienté vers des interfaces de ligne de commande plutôt que de la ligne de lecture. Il est également un peu plus opaque concernant la mise en mémoire tampon. (Quelqu'un qui a besoin d'un streaming ligne orientée lecteur sera probablement souhaitez modifier la taille du buffer). La readline module est ~1000 lignes, tout cela, avec des statistiques et de tests, est de 34.Voici une même version plus courte, sans les stats, à 19 lignes:
J'envelopper l'ensemble de la logique du quotidien de la ligne de traitement en tant que mnp module: ligne-kit
https://www.npmjs.com/package/line-kit
JS:
Je utiliser le code ci-dessous la lecture des lignes après avoir vérifier que ce n'est pas un répertoire et de ses pas inclus dans la liste des fichiers n'ont pas besoin d'être vérifier.
J'ai regardé à travers toutes les réponses ci-dessus, tous d'entre eux utilisent la bibliothèque tierce pour le résoudre. C'est avoir une solution simple dans le Nœud de l'API. e.g