12

我有一个大文件(utf8)。我知道fs.createReadStream可以创建流来读取大文件,但不同步。所以我尝试使用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));
4

5 回答 5

12

对于大文件,readFileSync可能会很不方便,因为它将整个文件加载到内存中。一种不同的同步方法是迭代调用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);
}
于 2014-01-19T16:30:30.797 回答
8

使用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');
于 2015-12-22T13:12:12.910 回答
4

使用readFileSync

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

如果指定了编码,则此函数返回一个字符串。否则它返回一个缓冲区。

附带说明一下,由于您使用的是节点,因此我建议您使用异步函数。

于 2011-09-25T11:17:17.780 回答
2

我构建了一个更简单的版本 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);
    }
}
于 2016-09-09T14:06:35.703 回答
1

两个潜在的问题,

  1. 开头的 3bytes BOM 你没有跳过
  2. 前 4 个字节不能很好地格式化为 UTF8 的字符(utf8 不是固定长度)
于 2011-09-25T13:06:35.363 回答