首页 > 解决方案 > 如何在 Vanilla JavaScript 中逐行读取文件?

问题描述

我有一个要阅读的文件(words.txt)。我想把它保存在一个数组中,但是文件中包含它太长了,所以我把它放在一个单独的文件中。我可以使用 URL 来获取它,但我也将文件放在与 javascript 文件相同的文件夹中。在不使用 jQuery 或 Node.js 的情况下,最简单的方法是什么?

标签: javascriptfile

解决方案


似乎您正在尝试分块读取一个非常大的文件,以免浏览器因内存过多而崩溃,对吗?如果没有,请告诉我。

虽然一般来说,要“逐行”阅读,人们(如何使用 Javascript 读取本地文本文件并逐行读取?)通常只是加载整个文件,然后将其拆分"\n",但这无法解决问题使用过大的文件使浏览器崩溃。

您正在寻找的是 FileReader 或 XMLHttpRequest 类的进度事件具体取决于您是从服务器获取本地、用户选择的文件还是文件。

它应该允许您以块的形式读取较大文件的一部分。随着块的进入,您可以跟踪换行符 ( \n),并相应地将每组文本保存在一个新数组中。

为了跟踪块,XMLHttpRequest 分块响应,只读取正在进行的最后一个响应,如果您可以在内存中保留累积的响应数据量,如果不是,您可以尝试如何编写 javascript中提到的数组缓冲区方法在客户端及时接收和解析“分块”响应?,甚至更好地使用答案中提到的 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));

推荐阅读