You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js监听文件变更并获取新增内容最后一行的实现需求

监听文件新增内容并提取最后一行(Node.js实现)

嘿,这个需求我熟!要实现每分钟监听文件新增的两行内容,并且每次只取新增部分的最后一行,咱们用Node.js原生的fs模块就能搞定,不用额外依赖第三方包,效率也够高。

核心思路

关键是不要每次都读整个文件(毕竟文件会越来越大),而是记录上次读到的文件字节位置,每次文件变更时只读取新增的部分,再从这部分内容里提取最后一行。

完整代码示例

直接上可运行的代码,你只需要把your-file.txt改成你要监听的文件路径就行:

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

// 替换成你要监听的文件路径
const targetFilePath = path.resolve(__dirname, 'your-file.txt');
let lastReadBytePosition = 0; // 记录上次读到文件的哪个字节位置

// 初始化:先获取当前文件的大小,作为初始读取起点
fs.stat(targetFilePath, (err, stats) => {
  if (err) {
    console.error('获取文件基础信息失败:', err);
    return;
  }
  lastReadBytePosition = stats.size;
});

// 启动文件监听
fs.watch(targetFilePath, (eventType) => {
  // 只处理文件内容变更的事件(忽略文件重命名等其他事件)
  if (eventType !== 'change') return;

  // 打开文件准备读取新增内容
  fs.open(targetFilePath, 'r', (err, fileDescriptor) => {
    if (err) {
      console.error('打开文件出错:', err);
      return;
    }

    // 获取当前文件的最新状态,计算需要读取的字节数
    fs.fstat(fileDescriptor, (err, stats) => {
      if (err) {
        console.error('获取文件状态失败:', err);
        fs.close(fileDescriptor);
        return;
      }

      const newBytesLength = stats.size - lastReadBytePosition;
      // 如果没有新增内容(比如重复触发的变更事件),直接关闭文件
      if (newBytesLength <= 0) {
        fs.close(fileDescriptor);
        return;
      }

      // 创建缓冲区来读取新增的字节内容
      const buffer = Buffer.alloc(newBytesLength);
      fs.read(
        fileDescriptor,
        buffer,
        0,
        newBytesLength,
        lastReadBytePosition,
        (err, bytesRead) => {
          if (err) {
            console.error('读取新增内容失败:', err);
            fs.close(fileDescriptor);
            return;
          }

          // 把缓冲区转成字符串,按换行符分割成数组
          const newContent = buffer.toString('utf8');
          const newLines = newContent.split('\n').filter(line => line.trim() !== '');

          // 提取新增内容的最后一行
          if (newLines.length > 0) {
            const lastAddedLine = newLines[newLines.length - 1];
            console.log('本次新增的最后一行:', lastAddedLine);
            // 这里可以把lastAddedLine传给你的业务逻辑,比如存数据库、发请求等
          }

          // 更新读取位置,下次只读新增部分
          lastReadBytePosition = stats.size;
          fs.close(fileDescriptor);
        }
      );
    });
  });
});

console.log(`已开始监听文件: ${targetFilePath}`);

关键细节说明

  • 记录读取位置:lastReadBytePosition变量会保存上次读到的文件字节数,每次只读取从这个位置到文件末尾的内容,避免重复读旧数据,效率拉满。
  • 过滤无效事件:fs.watch有时候会因为编辑器的保存机制触发多次变更事件,我们通过判断newBytesLength是否大于0来跳过没有新增内容的触发。
  • 处理空行:用filter(line => line.trim() !== '')过滤掉可能的空行,避免拿到无效内容。
  • 编码适配:示例用的是utf8编码,如果你的文件是GBK等其他编码,记得修改buffer.toString()的参数,比如buffer.toString('gbk')。

可选优化点

  • 如果你的文件可能被重命名或者替换,可以在监听出错时重新初始化lastReadBytePosition,或者结合fs.watchFile(不过fs.watch性能更好)。
  • 可以把监听逻辑封装成一个可复用的函数,比如:
function watchFileForLastAddedLine(filePath, onLastLineFound) {
  // 把上面的核心逻辑封装进来,最后调用onLastLineFound(lastAddedLine)
}

// 使用示例
watchFileForLastAddedLine('./log.txt', (line) => {
  console.log('拿到新增最后一行:', line);
});

内容的提问来源于stack exchange,提问作者ler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:25:30