【问题标题】:Node.js monitor file for changes and parse themNode.js 监控文件的变化并解析它们
【发布时间】:2016-07-05 03:37:48
【问题描述】:

我需要监控文件的更改。由于该文件有大量新条目,我需要“监控”该文件。我需要将新插入的内容添加到此文件中才能解析此内容。

我找到了这段代码:

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

【问题讨论】:

  • 我不知道如何仅获取例如在文件更改和内容插入时插入的内容。

标签: javascript node.js watch logfile


【解决方案1】:

这是一个示例,说明我如何使用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 不同)。

现在你有一个写入文件的行数组:)

【讨论】:

    【解决方案2】:

    在 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);
    });
    

    【讨论】:

    • 这似乎是最好的方法,但是当我对此进行测试并在文件顶部添加换行符时,它会将新行解析为空行?!
    • 如果你只在文件中添加换行符,它会返回一个空字符串,因为每个新行都会触发事件(换行符被删除)。如果你想一次解析多行,你必须自己重建字符串
    猜你喜欢
    • 1970-01-01
    • 2013-09-07
    • 2014-09-02
    • 2016-09-23
    • 1970-01-01
    • 2013-01-09
    • 2011-11-27
    • 1970-01-01
    • 2014-09-08
    相关资源
    最近更新 更多