Node.js 监视文件的变化并解析它们

Node.js monitor file for changes and parse them

我需要监视文件的更改。由于此文件有大量新条目,我需要 'monitor' 此文件。我需要将新插入的内容获取到此文件才能解析此内容。

我找到了这段代码:

fs.watchFile('var/log/query.log', function() {
console.log('File Changed ...');
//how to get the new line which is now inserted?
});

在 bash 你会用 tail --follow 做类似的事情。

还有一个包 tail 可用。 您可以观看文件,并通过事件获取新行:

const Tail = require('tail').Tail;
var tail = new Tail("var/log/query.log");
tail.watch()
tail.on("line", data => {
  console.log(data);
});

这是一个示例,说明我如何使用 fs.watchFile 来监控名为《炉石传说》的游戏的日志文件,并选取新的日志条目来监控玩游戏时发生的游戏事件。 https://github.com/chevex-archived/hearthstone-log-watcher/blob/master/index.js

var fs = require('fs');
var options = {
  logFile: '~/Library/Preferences/Blizzard/Hearthstone/log.config',
  endOfLineChar: require('os').EOL
};
// Obtain the initial size of the log file before we begin watching it.
var fileSize = fs.statSync(options.logFile).size;
fs.watchFile(options.logFile, function (current, previous) {
  // Check if file modified time is less than last time.
  // If so, nothing changed so don't bother parsing.
  if (current.mtime <= previous.mtime) { return; }

  // We're only going to read the portion of the file that
  // we have not read so far. Obtain new file size.
  var newFileSize = fs.statSync(options.logFile).size;
  // Calculate size difference.
  var sizeDiff = newFileSize - fileSize;
  // If less than zero then Hearthstone truncated its log file
  // since we last read it in order to save space.
  // Set fileSize to zero and set the size difference to the current
  // size of the file.
  if (sizeDiff < 0) {
    fileSize = 0;
    sizeDiff = newFileSize;
  }
  // Create a buffer to hold only the data we intend to read.
  var buffer = new Buffer(sizeDiff);
  // Obtain reference to the file's descriptor.
  var fileDescriptor = fs.openSync(options.logFile, 'r');
  // Synchronously read from the file starting from where we read
  // to last time and store data in our buffer.
  fs.readSync(fileDescriptor, buffer, 0, sizeDiff, fileSize);
  fs.closeSync(fileDescriptor); // close the file
  // Set old file size to the new size for next read.
  fileSize = newFileSize;

  // Parse the line(s) in the buffer.
  parseBuffer(buffer);
});

function stop () {
  fs.unwatchFile(options.logFile);
};

function parseBuffer (buffer) {
  // Iterate over each line in the buffer.
  buffer.toString().split(options.endOfLineChar).forEach(function (line) {
    // Do stuff with the line :)
  });
};

它首先计算文件的初始大小,因为在这个日志观察器模块中,我只想读取游戏正在写入的新数据。我不关心现有数据。然后它开始监视文件的变化。当更改处理程序触发时,我们检查修改时间是否真的更新,因为当我们关心的数据没有实际更改时,关于文件的一些其他更改可以触发处理程序。我们希望这个观察者尽可能地表现出色。

然后我们读取文件的新大小并计算与上次的差异。这准确地告诉我们要从文件中读取多少数据才能仅获取新写入的数据。然后我们将数据存储在缓冲区中并将其解析为字符串。只需按换行符拆分字符串即可。使用核心模块 os 获取 os.EOL 将为您 运行 所在的操作系统提供正确的行结束字符(windows 行结束字符不同于 linux/unix).

现在您已将一组行写入文件:)