node.js:将文本文件读入数组.(每行都是数组中的一个项目.)

cha*_*cko 147 javascript node.js

我想将一个非常非常大的文件读入node.js中的JavaScript数组.

所以,如果文件是这样的:

first line
two 
three
...
...
Run Code Online (Sandbox Code Playgroud)

我会有阵列:

['first line','two','three', ... , ... ] 
Run Code Online (Sandbox Code Playgroud)

该函数看起来像这样:

var array = load(filename); 
Run Code Online (Sandbox Code Playgroud)

因此,将它全部作为字符串加载然后拆分它的想法是不可接受的.

Fin*_*arr 401

同步:

var fs = require('fs');
var array = fs.readFileSync('file.txt').toString().split("\n");
for(i in array) {
    console.log(array[i]);
}
Run Code Online (Sandbox Code Playgroud)

异步:

var fs = require('fs');
fs.readFile('file.txt', function(err, data) {
    if(err) throw err;
    var array = data.toString().split("\n");
    for(i in array) {
        console.log(array[i]);
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 我发现在一个由Windows制作的文件上执行此操作,我不得不拆分\ r \n但是它破坏了Mac; 所以更健壮; _array = string.replace(/\r \n/g,'\n').split('\n'); 为两者工作 (13认同)
  • 谢谢.不幸的是我不得不编辑我的问题.我的意思是如何读取一个大型文件.在字符串中读取所有内容是不可接受的. (10认同)
  • +1 Stackoverflow中存在一些问题.现在,经常向下滚动后,我经常会找到高度评价的答案.这也是一个例子.它具有最高的投票率,但位于页面底部,最后一个.我认为Stackoverflow需要改进他们的排序算法. (5认同)
  • @shashwat 提出问题的人可以决定哪个是正确答案。在这种情况下,他们需要一个大文件的流媒体解决方案,将整个文件放在一个字符串中是不可接受的。真的没有错。 (3认同)
  • @WillHancock 为什么不使用 `os.EOL` 而不是那个怪物? (2认同)

mto*_*mis 88

如果您可以将最终数据放入数组中,那么您是否也可以将其放入字符串并将其拆分,如同建议的那样?在任何情况下,如果您想一次处理一行文件,您也可以尝试这样的事情:

var fs = require('fs');

function readLines(input, func) {
  var remaining = '';

  input.on('data', function(data) {
    remaining += data;
    var index = remaining.indexOf('\n');
    while (index > -1) {
      var line = remaining.substring(0, index);
      remaining = remaining.substring(index + 1);
      func(line);
      index = remaining.indexOf('\n');
    }
  });

  input.on('end', function() {
    if (remaining.length > 0) {
      func(remaining);
    }
  });
}

function func(data) {
  console.log('Line: ' + data);
}

var input = fs.createReadStream('lines.txt');
readLines(input, func);
Run Code Online (Sandbox Code Playgroud)

编辑:(回应phopkins的评论)我认为(至少在较新版本中)substring不会复制数据,但会创建一个特殊的SlicedString对象(快速浏览一下v8源代码).在任何情况下,这里都有一个修改,避免提到的子串(在一个文件上测试几兆字节的"所有工作,没有游戏使杰克成为一个沉闷的男孩"):

function readLines(input, func) {
  var remaining = '';

  input.on('data', function(data) {
    remaining += data;
    var index = remaining.indexOf('\n');
    var last  = 0;
    while (index > -1) {
      var line = remaining.substring(last, index);
      last = index + 1;
      func(line);
      index = remaining.indexOf('\n', last);
    }

    remaining = remaining.substring(last);
  });

  input.on('end', function() {
    if (remaining.length > 0) {
      func(remaining);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 我在大约2MB左右的文件上试过这个并且它很慢,比同步读取字符串的文件要慢得多.我认为问题是剩余的= remaining.substring线.节点的"数据"可能一次给你很多,并且每行的副本很快就会变成O(n ^ 2). (7认同)

zsw*_*ang 70

使用Node.js readline模块.

var fs = require('fs');
var readline = require('readline');

var filename = process.argv[2];
readline.createInterface({
    input: fs.createReadStream(filename),
    terminal: false
}).on('line', function(line) {
   console.log('Line: ' + line);
});
Run Code Online (Sandbox Code Playgroud)

  • Node已通过\n http://stackoverflow.com/a/32599033/3763850修复了该问题 (7认同)
  • 很好,干净的答案. (2认同)

hoj*_*jin 20

js:

var array = fs.readFileSync('file.txt', 'utf8').split('\n');
Run Code Online (Sandbox Code Playgroud)

ts:

var array = fs.readFileSync('file.txt', 'utf8').toString().split('\n');
Run Code Online (Sandbox Code Playgroud)

  • 为了防止上面抛出``TypeError: fs.readFileSync(...).split is not a function```,你应该像这样使用.toString():````var array = fs.readFileSync(' file.txt', 'utf8').toString().split('\n');``` (2认同)

Bla*_*son 11

使用readline(文档).这是一个读取css文件,解析图标并将它们写入json的示例

var results = [];
  var rl = require('readline').createInterface({
    input: require('fs').createReadStream('./assets/stylesheets/_icons.scss')
  });


  // for every new line, if it matches the regex, add it to an array
  // this is ugly regex :)
  rl.on('line', function (line) {
    var re = /\.icon-icon.*:/;
    var match;
    if ((match = re.exec(line)) !== null) {
      results.push(match[0].replace(".",'').replace(":",''));
    }
  });


  // readline emits a close event when the file is read.
  rl.on('close', function(){
    var outputFilename = './icons.json';
    fs.writeFile(outputFilename, JSON.stringify(results, null, 2), function(err) {
        if(err) {
          console.log(err);
        } else {
          console.log("JSON saved to " + outputFilename);
        }
    });
  });
Run Code Online (Sandbox Code Playgroud)


MiK*_*r13 7

本质上,这将做的工作:.replace(/\r\n/g,'\n').split('\n')。这适用于 Mac、Linux 和 Windows。

代码片段

同步:

const { readFileSync } = require('fs');

const array = readFileSync('file.txt').toString().replace(/\r\n/g,'\n').split('\n');

for(let i of array) {
    console.log(i);
}
Run Code Online (Sandbox Code Playgroud)

异步:

使用 fs.promises API 提供一组替代的异步文件系统方法,这些方法返回 Promise 对象而不是使用回调。 (无需承诺,您也可以使用 async-await,在 Node.js 版本 10.0.0 及之后可用)

const { readFile } = require('fs').promises;

readFile('file.txt', function(err, data) {
    if(err) throw err;

    const arr = data.toString().replace(/\r\n/g,'\n').split('\n');

    for(let i of arr) {
        console.log(i);
    }
});
Run Code Online (Sandbox Code Playgroud)

更多关于 \r & \n 在这里:\r\n, \r 和 \n 它们之间有什么区别?


Abd*_*UMI 6

file.lines使用JFile包

var JFile=require('jfile');

var myF=new JFile("./data.txt");
myF.lines // ["first line","second line"] ....
Run Code Online (Sandbox Code Playgroud)

别忘了:

npm install jfile --save
Run Code Online (Sandbox Code Playgroud)


Gab*_*mas 5

使用BufferedReader,但该函数应该是异步的:

var load = function (file, cb){
    var lines = [];
    new BufferedReader (file, { encoding: "utf8" })
        .on ("error", function (error){
            cb (error, null);
        })
        .on ("line", function (line){
            lines.push (line);
        })
        .on ("end", function (){
            cb (null, lines);
        })
        .read ();
};

load ("file", function (error, lines){
    if (error) return console.log (error);
    console.log (lines);
});
Run Code Online (Sandbox Code Playgroud)


Kri*_*ofe 5

要将大文件读入数组,您可以逐行或逐块读取。

逐行参考我的回答这里

var fs = require('fs'),
    es = require('event-stream'),

var lines = [];

var s = fs.createReadStream('filepath')
    .pipe(es.split())
    .pipe(es.mapSync(function(line) {
        //pause the readstream
        s.pause();
        lines.push(line);
        s.resume();
    })
    .on('error', function(err) {
        console.log('Error:', err);
    })
    .on('end', function() {
        console.log('Finish reading.');
        console.log(lines);
    })
);
Run Code Online (Sandbox Code Playgroud)

逐块参考这篇文章

var offset = 0;
var chunkSize = 2048;
var chunkBuffer = new Buffer(chunkSize);
var fp = fs.openSync('filepath', 'r');
var bytesRead = 0;
while(bytesRead = fs.readSync(fp, chunkBuffer, 0, chunkSize, offset)) {
    offset += bytesRead;
    var str = chunkBuffer.slice(0, bytesRead).toString();
    var arr = str.split('\n');

    if(bytesRead = chunkSize) {
        // the last item of the arr may be not a full line, leave it to the next chunk
        offset -= arr.pop().length;
    }
    lines.push(arr);
}
console.log(lines);
Run Code Online (Sandbox Code Playgroud)