我想把一个非常非常大的文件读入node。js中的JavaScript数组。
所以,如果文件是这样的:
first line
two
three
...
...
我有一个数组:
['first line','two','three', ... , ... ]
函数看起来是这样的:
var array = load(filename);
因此,将其全部作为字符串加载,然后将其拆分的想法是不可接受的。
我想把一个非常非常大的文件读入node。js中的JavaScript数组。
所以,如果文件是这样的:
first line
two
three
...
...
我有一个数组:
['first line','two','three', ... , ... ]
函数看起来是这样的:
var array = load(filename);
因此,将其全部作为字符串加载,然后将其拆分的想法是不可接受的。
当前回答
如果你能把最终的数据放入一个数组,那么你不也能把它放入一个字符串中并分割它吗? 在任何情况下,如果你想一次处理一行文件,你也可以尝试这样做:
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);
编辑:(回应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);
}
});
}
其他回答
使用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);
});
另一个答案是使用npm包。nexline包允许用户逐行异步读取文件:
"use strict";
import fs from 'fs';
import nexline from 'nexline';
const lines = [];
const reader = nexline({
input: fs.createReadStream(`path/to/file.ext`)
});
while(true) {
const line = await reader.next();
if(line === null) break; // line is null if we reach the end
if(line.length === 0) continue; // Ignore empty lines
// Process the line here - below is just an example
lines.push(line);
}
即使您的文本文件大于允许的最大字符串长度,这种方法也可以工作,从而避免“错误:不能创建超过0x1fffffe8个字符的字符串”错误。
如果你能把最终的数据放入一个数组,那么你不也能把它放入一个字符串中并分割它吗? 在任何情况下,如果你想一次处理一行文件,你也可以尝试这样做:
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);
编辑:(回应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);
}
});
}
为了将每行作为数组中的一项,在Node.js v18.11.0中添加了一个逐行读取文件的新函数
filehandle.readLines([选项])
这就是如何将此用于文本文件,您希望读取文件并将每行放入数组中
import { open } from 'node:fs/promises';
const arr = [];
myFilereader();
async function myFileReader() {
const file = await open('./TextFileName.txt');
for await (const line of file.readLines()) {
arr.push(line);
}
console.log(arr)
}
为了了解更多read Node.js文档,这里有文件系统readlines()的链接: https://nodejs.org/api/fs.html#filehandlereadlinesoptions
本质上,这将完成工作:.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);
}
异步:
用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);
}
});
更多关于\r和\n的信息在这里:\r\n, \r和\n它们之间有什么区别?