Nodejs监控文件内容变化并获取最新添加的内容
来源:互联网 发布:尔湾安全知乎 编辑:程序博客网 时间:2024/05/18 13:27
现在有个需求是这样:
“某个应用会产生日志文件,使用nodejs开发程序完成对日志的操作:当程序启动的时候首先获取日志所有内容并作相关处理,然后对日志监控,如果有新的内容添加进来,立即获取到最新内容继续做处理”。当然,这里我把需求简化了,主要就是下面酱紫:
接触nodejs不到8小时,只有从nodejs的中文api找切入点,分别找到了两个模块
fs、ReadLine
watch和watchFile实现文件的监听,代码如下(watch):
var fs = require('fs');// 引入fs 模块var filePath = 'input.txt';fs.watch(filePath, function (event, filename) { console.log('event is: ' + event); if (filename) { console.log('filename provided: ' + filename); //readTxt(); } else { console.log('filename not provided'); } }});console.log(filePath + ' 被监听中...');
效果图如下:
只要是文件被修改后保存,程序会立即检测到(这里我有个疑问,我修改文件保存后,为什么会打印两遍?)
ReadLine的功能就是按行读取文件,相关代码如下:
var fs = require('fs');var readline = require('readline');// 引入readline模块var filename = 'input.txt';var rl = readline.createInterface({ input: fs.createReadStream(filename,{ enconding:'utf8' }), output: null});rl.on('line', function(line) { if (line) { console.log(line.toString()); }}).on('close', function() { console.log('读文件结束!');});
对于没有用过nodejs但想学nodejs的人来说,我建议先把菜鸟学校里的教程看一遍,我接触nodejs的当天晚上就把上面的教程过了一遍。这样再深入的话会很快。跑题了。。。
上面代码的结果如图:
有了这两段代码,我很快有了方案
- 程序开始使用readline将原有内容逐行读取并处理;
- 处理完后使用watch监听文件;
- 文件变动再次使用readline读文件内容,依次放在一个数组里,然后获取最后一个;
然而并非我想象的那样,如果一次插入多条内容,那我这个方案就不行了。
我想找有关file的第三方库,然而并没有我想要的,还是要自己写!
最后发现了watch里有个回调函数
fs.watchFile('input.text', function (curr, prev) { console.log('the current mtime is: ' + curr.mtime); console.log('the previous mtime was: ' + prev.mtime);});
请注意这两个参数curr,prev,我试着把curr的内容打印出来,如下:
{ dev: 997878, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 844424930190818, size: 175, blocks: undefined, atime: Tue Jun 28 2016 20:36:43 GMT+0800 (中国标准时间), mtime: Tue Jun 28 2016 22:53:46 GMT+0800 (中国标准时间), ctime: Tue Jun 28 2016 22:53:46 GMT+0800 (中国标准时间), birthtime: Mon Jun 27 2016 20:36:56 GMT+0800 (中国标准时间) }
我注意到里面有个size,这难道是文件的字节数?答案是的,那这样问题就解决了,新的方案出来了:
- 使用readline先逐行获取内容并解析
- 使用watchfile监控文件,当文件有内容添加使用curr和prev里的size来读取添加的内容
- 得到新的内容,通过’\n\r’或’\n’将其截取成数组,这样就得到了一行一行的内容
这里需要用到fs的open和read
fs.open(path, flags, [mode], callback)fs.read(fd, buffer, offset, length, position, callback)
两个方法真的是绝配啊~~~看看中文api,很详细,配合的代码如下:
fs.open(filePath,'a+',function(error,fd){ var buffer; var remainder = null; fs.watchFile(filePath,{ persistent: true, interval: 1000 },function(curr, prev){ //console.log(curr); if(curr.mtime>prev.mtime){ //文件内容有变化,那么通知相应的进程可以执行相关操作。例如读物文件写入数据库等 buffer = new Buffer(curr.size - prev.size);// 创建一个缓冲,长度为(当前文件大小-文件上一个状态的大小) fs.read(fd,buffer,0,(curr.size - prev.size),prev.size,function(err, bytesRead, buffer){ console.log(buffer.toString());//新增加的内容 }); }else{ console.log('文件读取错误'); } });});
每次文件改动(这里主要指文件有新的内容追加上,没有考虑删除修改等情况),就将上一状态的大小作为本次读文件的起始位置
position—>prev.size
offset—>0 //在新建buffer的其实位置开始写入
length—>(curr.size - prev.size)
完整的代码如下:
var fs = require('fs');var readline = require('readline');var filename = 'input.txt';var logsArr = new Array();var listenArr = new Array();function init(){ sendHisLogs(filename, listenLogs);}function sendHisLogs(filename,listenLogs){ var rl = readline.createInterface({ input: fs.createReadStream(filename,{ enconding:'utf8' }), output: null, terminal: false //这个参数很重要 }); rl.on('line', function(line) { if (line) { logsArr.push(line.toString()); } }).on('close', function() { for(var i = 0 ;i<logsArr.length;i++){ console.log('发送历史信号: ' + logsArr[i]); //generateLog(logsArr[i]) } listenLogs(filename); });}function generateLog(str){ var regExp = /(\[.+?\])/g;//(\\[.+?\\]) var res = str.match(regExp); console.log(res); for(i=0;i<res.length;i++){ res[i] = res[i].replace('[','').replace(']',''); //发送历史日志 }}var listenLogs = function(filePath){ console.log('日志监听中...'); var fileOPFlag="a+"; fs.open(filePath,fileOPFlag,function(error,fd){ var buffer; var remainder = null; fs.watchFile(filePath,{ persistent: true, interval: 1000 },function(curr, prev){ console.log(curr); if(curr.mtime>prev.mtime){ //文件内容有变化,那么通知相应的进程可以执行相关操作。例如读物文件写入数据库等 buffer = new Buffer(curr.size - prev.size); fs.read(fd,buffer,0,(curr.size - prev.size),prev.size,function(err, bytesRead, buffer){ generateTxt(buffer.toString()) }); }else{ console.log('文件读取错误'); } }); function generateTxt(str){ // 处理新增内容的地方 var temp = str.split('\r\n'); for(var s in temp){ console.log(temp[s]); } } });}function getNewLog(path){ console.log('做一些解析操作');}init();
运行结果如下:
代码我先上传到这里
我这样写只是完成了我当前的需求,在接下来学习nodejs的过程中,我会对其进行优化,最后能将其打包上传到npm上!
nodejs有点让我抓狂了,我开始喜欢上它了~~~
- Nodejs监控文件内容变化并获取最新添加的内容
- linux之tail,监控文件内容变化
- Flume之监控文件内容变化
- 监控log文件变化进行读出变化的内容供分析的源码类
- edittext添加内容发生变化的监听
- 如何监控文件夹内容变化
- flume 1.7 新接口,监控文件内容变化,且监控目录内新增文件变化
- 获取 JTextField的 内容变化的事件
- 工具类commons-io的Tailer用法,用来监控文件内容的变化情况
- 读取文件内容并将内容添加到节点
- 针对文件目录内容变化的检测
- Javascript实现输入内容变化的监控通知
- Python入门:请重新输入并获取最新的一次输入的内容
- MFC获取文件的内容
- 获取文件内容的大小
- Swift - 文本输入框内容改变时响应,并获取最新内容
- 打印输入的内容并添加行号
- 利用nodejs监控文件变化并使用sftp上传到服务器
- qemu
- 事务的简单应用
- c++运算符的重载
- 【Arduino官方教程第一辑】示例程序 6-4 超声波测距传感器
- Xcode各版本官方下载及百度云盘下载, Mac和IOS及Xcode版本历史.
- Nodejs监控文件内容变化并获取最新添加的内容
- Java面向对象概念
- WPF中的binding(九)- 使用Binding的RelativeSource
- 1010
- profile
- Andrew Ng-ML-第三讲
- osgi + felix example2b编写
- PHP几个防SQL注入攻击自带函数区别
- vijos1022(强联通分量模版题)