需求
tail -f的命令效果为挂起一个服务监控一个文件,当文件结尾内容输出,并当文件有新内容后追加输出。
分析
监控文件可以用 fs.watchFile实现,fs.watchFile会挂起一个服务,监视文件的变化。 每次访问文件时都会调用回调该方法的listener,下面是官方文档的例子:
import { watchFile } from 'fs';
watchFile('message.text', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
所以在该方法内每次读取最新增加的数据进行输出,所以在这个特殊的循环里需要统计和计算出每次文件读到的位置和新增数据的大小然后用fs.readSync读出来。
踩坑点
每当文件发生变化后,原先使用fs.openSync的到的fd使用fs.readSync获取不到最新的数据,所以要重新获取。
代码
import * as fs from 'fs';
const path = '/Users/lizechen/WorkSpace/train-lzc/serialport-test/test.txt';
const firstBufferSize = 100;
let beforeSize = fs.statSync(path).size;
const fd = fs.openSync(path, 'r');
let firstBuffer;
if (beforeSize > firstBufferSize) {
firstBuffer = Buffer.alloc(firstBufferSize);
fs.readSync(fd, firstBuffer, { position: beforeSize - firstBufferSize });
} else {
firstBuffer = Buffer.alloc(beforeSize)
fs.readSync(fd, firstBuffer);
}
process.stdout.write(firstBuffer.toString());
fs.watchFile(path, (curr, prev) => {
const newSize = fs.statSync(path).size;
if (newSize > beforeSize) {
const buffer = Buffer.alloc(newSize - beforeSize);
const fd = fs.openSync(path, 'r');
fs.readSync(fd, buffer, { position: beforeSize });
beforeSize = newSize
process.stdout.write(buffer.toString());
}
});