在 Node JS 中只读取文件第一行的最有效方法是什么?

What is the most efficient way to read only the first line of a file in Node JS?

假设您有很多长文本文件,您只需要从每个文件的第一行提取数据(无需阅读任何进一步的内容)。在 Node JS 中最好的方法是什么?

谢谢!

//给你;

var lineReader = require('line-reader');
var async = require('async');

exports.readManyFiles = function(files) {
    async.map(files, 
        function(file, callback))
            lineReader.open(file, function(reader) {
              if (reader.hasNextLine()) {
                reader.nextLine(function(line) {
                  callback(null,line);
                });
              }
            });
        },
        function(err, allLines) {
            //do whatever you want to with the lines
        })
}

我最终采用了这个解决方案,这似乎是迄今为止我见过的性能最高的解决方案:

var fs = require('fs');
var Q = require('q');

function readFirstLine (path) {
  return Q.promise(function (resolve, reject) {
    var rs = fs.createReadStream(path, {encoding: 'utf8'});
    var acc = '';
    var pos = 0;
    var index;
    rs
      .on('data', function (chunk) {
        index = chunk.indexOf('\n');
        acc += chunk;
        index !== -1 ? rs.close() : pos += chunk.length;
      })
      .on('close', function () {
        resolve(acc.slice(0, pos + index));
      })
      .on('error', function (err) {
        reject(err);
      })
  });
}

为了方便,我创建了一个 npm 模块,命名为“firstline”。

感谢@dandavis 建议使用 String.prototype.slice()!

请试试这个:

https://github.com/yinrong/node-line-stream-util#get-head-lines

一旦得到头条线,它就会取消上游。

对于这种情况几乎有一个内置模块 - readline。它避免弄乱块等。代码如下所示:

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

async function getFirstLine(pathToFile) {
  const readable = fs.createReadStream(pathToFile);
  const reader = readline.createInterface({ input: readable });
  const line = await new Promise((resolve) => {
    reader.on('line', (line) => {
      reader.close();
      resolve(line);
    });
  });
  readable.close();
  return line;
}

我知道这并不能完全回答问题,但对于那些正在寻找 READABLEsimple 方法的人来说:

const fs = require('fs').promises;

async function getFirstLine(filePath) {
    const fileContent = await fs.readFile(filePath, 'utf-8');
    return (fileContent.match(/(^.*)/) || [])[1] || '';
} 

注意:

  • 当然,这只适用于文本文件,根据您的描述我假设您使用的是文本文件
  • 这个处理空文件并且return一个空字符串
  • 这个正则表达式非常高效,因为它很简单(没有 OR 条件`或复杂的匹配)并且只读取第一行

Node.js >= 16

在 Node.js 的所有当前版本中,readline.createInterface 可以用作异步迭代器,逐行读取文件 - 或者仅读取第一行。这也可以安全地用于空文件。

不幸的是,错误处理逻辑在 16 之前的 Node.js 版本中被破坏,其中某些文件系统错误可能不会被捕获,即使代码被包装在 try-catch 块中,因为方式异步错误在流中传播。所以我建议只在 Node.js >= 16.

中使用此方法
import { createReadStream } from "fs";
import { createInterface } from "readline";

async function readFirstLine(path) {
    const inputStream = createReadStream(path);
    try {
        for await (const line of createInterface(inputStream)) return line;
        return ''; // If the file is empty.
    }
    finally {
        inputStream.destroy(); // Destroy file stream.
    }
}

const firstLine = await readFirstLine("path/to/file");