【问题标题】:Node.js "readline" + "fs. createReadStream" : Specify start & end line numberNode.js "readline" + "fs.createReadStream" : 指定开始和结束行号
【发布时间】:2021-07-01 13:23:05
【问题描述】:

https://nodejs.org/api/readline.html

为逐行读取 CSV 等大文件提供此解决方案:

const { createReadStream } = require('fs');
const { createInterface } = require('readline');

(async function processLineByLine() {
  try {
    const rl = createInterface({
      input: createReadStream('big-file.txt'),
      crlfDelay: Infinity
    });

    rl.on('line', (line) => {
      // Process the line.
    });

    await once(rl, 'close');

    console.log('File processed.');
  } catch (err) {
    console.error(err);
  }
})();

但我不想从头到尾读取整个文件,而是从第 1 行到第 10000、20000 到 30000 等的部分内容。

基本上,我希望能够为我的函数的给定运行设置“开始”和“结束”行。

这对readlinefs.createReadStream 可行吗? 如果不是,请建议替代方法。

PS:这是一个大文件(大约 1 GB),将其加载到内存中会导致内存问题。

【问题讨论】:

  • 线条的大小都一样吗?
  • 除非您的行是固定的、相同的长度,否则如果不从文件开头读取并计算行数,直到您到达第 10,000 行,就无法知道第 10,000 行从哪里开始。这就是具有可变长度行的文本文件的工作方式。没有办法绕过它,除非您将文件预处理为更有效的格式(如数据库)或创建行位置索引。
  • 嗯,大文件的内存问题可以通过使用流来解决,在任何给定时间,无论整个文件有多大,内存中都只有一小部分文件。
  • @lawrence 我想跳过迭代。

标签: node.js fs large-files node-streams large-file-support


【解决方案1】:

但我不想从头到尾读取整个文件,而是从第 1 行到第 10000 行、从第 20000 到第 30000 行等部分读取。

除非您的行是固定的、相同的长度,否则如果不从文件开头读取并计算行数,直到您到达第 10,000 行,就无法知道第 10,000 行从哪里开始。这就是具有可变长度行的文本文件的工作方式。文件中的行不是文件系统知道的任何物理结构。对于文件系统来说,文件只是一个巨大的数据块。行的概念是我们在更高层次上发明的,因此文件系统或操作系统对行一无所知。知道行在哪里的唯一方法是读取数据并通过搜索行分隔符将其“解析”成行。因此,只有从文件开头开始搜索第 10,000 行分隔符并计数,才能找到第 10,000 行。

没有办法绕过它,除非您将文件预处理为更有效的格式(如数据库)或创建行位置索引。

基本上,我希望能够为我的函数的给定运行设置“开始”和“结束”行。

做到这一点的唯一方法是提前“索引”数据,这样您就已经知道每行的开始/结束位置。一些用于处理非常大文件的文本编辑器会这样做。他们通读文件(可能是懒惰地)读取每一行,并为每行开始的文件偏移量建立一个内存索引。然后,他们可以通过查询索引并从文件中读取该组数据来检索特定的行块。

这对 readline 和 fs.createReadStream 可行吗?

如果没有固定长度的行,如果不从头开始计数,就无法知道文件中第 10,000 行从哪里开始。

这是一个大文件(大约 1 GB)并且将其加载到内存中会导致内存问题。

使用 linereader 模块或其他执行类似操作的其他模块一次流式传输文件将很好地处理内存问题,以便在任何给定时间只有来自文件的数据块在内存中。即使在小内存系统中,您也可以通过这种方式处理任意大的文件。

【讨论】:

  • 感谢您如此迅速而彻底地回答。
【解决方案2】:

新行只是一个字符(如果您在 Windows 上,则为两个字符),如果不处理文件,您将无法知道这些字符的位置。

但是,您只能读取文件中的某个字节范围。如果您知道每行包含 64 个字节这一事实,则可以通过从 6400 字节开始读取来跳过前 100 行,而在字节 12800 停止读取则只能读取 100 行。

createReadStream 文档中提供了有关如何指定起点和终点的详细信息。

【讨论】:

    猜你喜欢
    • 2021-04-15
    • 2021-11-13
    • 2021-04-14
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多