您似乎正在尝试分块读取一个非常大的文件,以免因内存过多而导致浏览器崩溃,对吗?如果没有,请告诉我。
虽然一般来说,要“逐行”阅读,人们 (How to use Javascript to read local text file and read line by line?) 通常只是加载整个文件,然后将其拆分为 "\n",但这无法解决浏览器崩溃的问题过大的文件。
您要查找的是用于 FileReader 或 XMLHttpRequest 类的 progress event,具体取决于您是从服务器获取本地、用户选择的文件还是文件。
它应该允许您以块的形式读取较大文件的一部分。随着块的进入,您可以跟踪换行符 (\n),并相应地将每组文本保存在一个新数组中。
为了跟踪块,XMLHttpRequest chunked response, only read last response in progress,如果您可以在内存中保存累积的响应数据量,如果不是,您可以尝试How to write javascript in client side to receive and parse `chunked` response in time? 中提到的数组缓冲区方法,甚至更好,使用答案中提到的 ReadableStream 类以及 fetch。
基于该答案以及其他答案,我尝试组合一个函数,该函数将为您在读取每一行时提供回调,并按块读取总 URL,即使块本身可能略多于一次 1 行,但它是我能想到的最接近客户端 JavaScript 的,如果它有效,请告诉我:
function readLineByLine(url, callback) {
fetch(url)
.then(response => {
let fetchReader = response.body.getReader(),
decoder = new TextDecoder(),
currentLineData = "",
totalLines = [];
fetchReader.read()
.then(function readData(progress) {
let thisJustInSomeData = decoder.decode(
progress.value || "",
{
stream: !progress.done
}
),
lines = thisJustInSomeData.split("\n");
if(lines.length < 2) {
currentLineData += lines[0];
} else {
lines.forEach((x, i, a) => {
currentLineData += x;
totalLines.push(currentLineData);
if(i < lines.length - 1) {
currentLineData = "";
}
});
}
totalLines.forEach(line => {
callback({line});
});
totalLines = []
if(progress.done) {
callback({done: progress.done})
return;
}
return readData();
})
});
}
然后调用它
readLineByLine("someURLorTxtFileWithLotsOfLines", line => console.log(line));