2011-09-25 18 views
8

Tengo un archivo grande (utf8). Sé que fs.createReadStream puede crear una secuencia para leer un archivo grande, pero no sincronizado. Así que trato de usar fs.readSync, pero el texto de lectura está roto como "迈�".sincronización nodejs leer archivo grande línea por línea?

var fs = require('fs'); 
var util = require('util'); 
var textPath = __dirname + '/people-daily.txt'; 
var fd = fs.openSync(textPath, "r"); 
var text = fs.readSync(fd, 4, 0, "utf8"); 
console.log(util.inspect(text, true, null)); 
+0

¿Está seguro de que el archivo está codificado con utf8? – thejh

+0

sí, Unicode (UTF-8) y Unix (LF) – nroe

+0

Creo que quiere decir "sincrónico" en lugar de "sincronizado". – hippietrail

Respuesta

4

Uso readFileSync:

fs.readFileSync (filename, [codificación]) versión síncrona de fs.readFile. Devuelve el contenido del nombre de archivo.

Si se especifica la codificación, esta función devuelve una cadena. De lo contrario, devuelve un búfer.

En una nota lateral, ya que está utilizando el nodo, recomendaría el uso de funciones asíncronas.

problemas
+2

El archivo es grande, creo que fs.readFileSync es no es Buena idea. – nroe

+1

@nroe, entonces ¿por qué estás pidiendo una lectura sincrónica? Por supuesto, eso no funcionará con un archivo grande. – Tom

+2

@Tom, nroe probablemente desee recibir las líneas como valores devueltos a las llamadas de lectura. Parte del código que implementa esto está disponible en [esta publicación del blog] (http://blog.jaeckel.com/2010/03/i-tried-to-find-example-on-using-node.html) (no mío). –

1

dos potenciales,

  1. 3bytes lista de materiales al principio que no salta
  2. primeros 4bytes no pueden ser así dar formato a caracteres de UTF8 (longitud UTF-8 no es fijo)
9

Para grandes archivos, readFileSync puede ser un inconveniente, ya que carga todo el archivo en la memoria. Un enfoque síncrono diferente es llamar iterativamente al readSync, leer pequeños bits de datos a la vez, y procesar las líneas tal como vienen. El siguiente fragmento de código implementa este enfoque y de forma sincrónica procesa una línea a la vez desde el archivo 'test.txt':

var fs = require('fs'); 
var filename = 'test.txt' 

var fd = fs.openSync(filename, 'r'); 
var bufferSize = 1024; 
var buffer = new Buffer(bufferSize); 

var leftOver = ''; 
var read, line, idxStart, idx; 
while ((read = fs.readSync(fd, buffer, 0, bufferSize, null)) !== 0) { 
    leftOver += buffer.toString('utf8', 0, read); 
    idxStart = 0 
    while ((idx = leftOver.indexOf("\n", idxStart)) !== -1) { 
    line = leftOver.substring(idxStart, idx); 
    console.log("one line read: " + line); 
    idxStart = idx + 1; 
    } 
    leftOver = leftOver.substring(idxStart); 
} 
+0

Genial, ¡gracias por eso! – Benvorth

7

uso https://github.com/nacholibre/node-readlines

var lineByLine = require('n-readlines'); 
var liner = new lineByLine('./textFile.txt'); 

var line; 
var lineNumber = 0; 
while (line = liner.next()) { 
    console.log('Line ' + lineNumber + ': ' + line.toString('ascii')); 
    lineNumber++; 
} 

console.log('end of line reached'); 
2

construí la respuesta de una versión más simple que JB Kohn usa split() en el buffer. Funciona en los archivos más grandes que probé.

/* 
* Synchronously call fn(text, lineNum) on each line read from file descriptor fd. 
*/ 
function forEachLine (fd, fn) { 
    var bufSize = 64 * 1024; 
    var buf = new Buffer(bufSize); 
    var leftOver = ''; 
    var lineNum = 0; 
    var lines, n; 

    while ((n = fs.readSync(fd, buf, 0, bufSize, null)) !== 0) { 
     lines = buf.toString('utf8', 0 , n).split('\n'); 
     lines[0] = leftOver+lines[0];  // add leftover string from previous read 
     while (lines.length > 1) {   // process all but the last line 
      fn(lines.shift(), lineNum); 
      lineNum++; 
     } 
     leftOver = lines.shift();   // save last line fragment (may be '') 
    } 
    if (leftOver) {       // process any remaining line 
     fn(leftOver, lineNum); 
    } 
} 
+0

Quizás cambie 'split ('\ n')' a 'split (/ \ r? \ N /)' para admitir posibles terminaciones de línea de Windows, también? – rob3c

Cuestiones relacionadas