nodejs同步逐行读取大文件?

我有一个大文件(utf8)。 我知道fs.createReadStream可以创buildstream来读取大文件,但不能同步。 所以我尝试使用fs.readSync ,但阅读文本被打破,如"迈 "

 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)); 

对于大文件, readFileSync可能不方便,因为它将整个文件加载到内存中。 一种不同的同步方法是迭代地调用readSync ,一次读取less量的数据,并在处理这些readSync 。 下面这段代码实现了这种方法,每次从文件“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); } 

使用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'); 

使用readFileSync :

fs.readFileSync(filename,[encoding])fs.readFile的同步版本。 返回文件名的内容。

如果指定了编码,那么这个函数返回一个string。 否则它会返回一个缓冲区。

在一个侧面说明,因为你正在使用节点,我build议使用asynchronousfunction。

两个潜在的问题,

  1. 3字节的BOM在一开始就没有跳过
  2. 前4bytes不能格式化为UTF8的字符(utf8不是固定长度)

我build立了一个简单的版本JB Kohn的答案,在缓冲区上使用split()。 它适用于我尝试的较大的文件。

 /* * 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); } }