使用 NodeJS 重播日志文件,就好像它是实时发生的一样
Replay a log file with NodeJS as if it were happening in real-time
我有一个日志文件,其中包含从名为 Flarm 的系统捕获的大约 14.000 个飞机位置数据点,它看起来像这样:
{"addr":"A","time":1531919658.578100,"dist":902.98,"alt":385,"vs":-8}
{"addr":"A","time":1531919658.987861,"dist":914.47,"alt":384,"vs":-7}
{"addr":"A","time":1531919660.217471,"dist":925.26,"alt":383,"vs":-7}
{"addr":"A","time":1531919660.623466,"dist":925.26,"alt":383,"vs":-7}
我需要做的是找到一种方法 'play' 这个文件实时返回(就像它现在正在发生一样,即使它是预先录制的),并在任何时候发出一个事件日志条目 'occurs'。该文件未被添加,它是预先录制的,播放将在稍后阶段进行。
之所以这样做是因为我在开发的时候没有接触到接收设备
我能想到的唯一方法是为每个日志条目设置超时,但这似乎不是正确的方法。此外,这个过程必须扩展到更长的录音(这个只有一个小时)。
还有其他方法吗?
假设您想可视化飞行日志,您可以使用 fs
watch 如下所示,查看日志文件的变化:
fs.watch('somefile', function (event, filename) {
console.log('event is: ' + event);
if (filename) {
console.log('filename provided: ' + filename);
} else {
console.log('filename not provided');
}
});
代码摘录来自here. For more information on fs.watch()
check out here
然后,为了在前端进行无缝更新,您可以在查看日志文件的服务器上设置一个 Websocket,并通过该套接字将新添加的行发送到前端。
在前端获取数据后,您可以在那里将其可视化。虽然我之前没有做过任何飞行可视化项目,但我已经使用 D3js 来可视化其他内容(声音、数值数据、度量分析等)几次,而且每次都能完成。
如果你想 "play them back" 与实际时差,setTimeout
几乎就是你必须做的。
const processEntry = (entry, index) => {
index++;
const nextEntry = getEntry(index);
if (nextEntry == null) return;
const timeDiff = nextEntry.time - entry.time;
emitEntryEvent(entry);
setTimeout(processEntry, timeDiff, nextEntry, index);
};
processEntry(getEntry(0), 0);
这会发出当前条目,然后根据差异设置超时,直到下一个条目。
getEntry
可以从预填充数组中获取行,也可以根据索引单独获取行。在后一种情况下,只有两行数据只会同时存在于内存中。
终于成功了! setTimeout 结果是答案,并结合 Lucas S 的输入。这就是我最终得到的结果:
const EventEmitter = require('events');
const fs = require('fs');
const readable = fs.createReadStream("./data/2018-07-18_1509log.json", {
encoding: 'utf8',
fd: null
});
function read_next_line() {
var chunk;
var line = '';
// While this is a thing we can do, assign chunk
while ((chunk = readable.read(1)) !== null) {
// If chunk is a newline character, return the line
if (chunk === '\n'){
return JSON.parse(line);
} else {
line += chunk;
}
}
return false;
}
var lines = [];
var nextline;
const processEntry = () => {
// If lines is empty, read a line
if (lines.length === 0) lines.push(read_next_line());
// Quit here if we've reached the last line
if ((nextline = read_next_line()) == false) return true;
// Else push the just read line into our array
lines.push(nextline);
// Get the time difference in milliseconds
var delay = Number(lines[1].time - lines[0].time) * 1000;
// Remove the first line
lines.shift();
module.exports.emit('data', lines[0]);
// Repeat after the calculated delay
setTimeout(processEntry, delay);
}
var ready_to_start = false;
// When the stream becomes readable, allow starting
readable.on('readable', function() {
ready_to_start = true;
});
module.exports = new EventEmitter;
module.exports.start = function() {
if (ready_to_start) processEntry();
if (!ready_to_start) return false;
}
我有一个日志文件,其中包含从名为 Flarm 的系统捕获的大约 14.000 个飞机位置数据点,它看起来像这样:
{"addr":"A","time":1531919658.578100,"dist":902.98,"alt":385,"vs":-8}
{"addr":"A","time":1531919658.987861,"dist":914.47,"alt":384,"vs":-7}
{"addr":"A","time":1531919660.217471,"dist":925.26,"alt":383,"vs":-7}
{"addr":"A","time":1531919660.623466,"dist":925.26,"alt":383,"vs":-7}
我需要做的是找到一种方法 'play' 这个文件实时返回(就像它现在正在发生一样,即使它是预先录制的),并在任何时候发出一个事件日志条目 'occurs'。该文件未被添加,它是预先录制的,播放将在稍后阶段进行。
之所以这样做是因为我在开发的时候没有接触到接收设备
我能想到的唯一方法是为每个日志条目设置超时,但这似乎不是正确的方法。此外,这个过程必须扩展到更长的录音(这个只有一个小时)。
还有其他方法吗?
假设您想可视化飞行日志,您可以使用 fs
watch 如下所示,查看日志文件的变化:
fs.watch('somefile', function (event, filename) {
console.log('event is: ' + event);
if (filename) {
console.log('filename provided: ' + filename);
} else {
console.log('filename not provided');
}
});
代码摘录来自here. For more information on fs.watch()
check out here
然后,为了在前端进行无缝更新,您可以在查看日志文件的服务器上设置一个 Websocket,并通过该套接字将新添加的行发送到前端。
在前端获取数据后,您可以在那里将其可视化。虽然我之前没有做过任何飞行可视化项目,但我已经使用 D3js 来可视化其他内容(声音、数值数据、度量分析等)几次,而且每次都能完成。
如果你想 "play them back" 与实际时差,setTimeout
几乎就是你必须做的。
const processEntry = (entry, index) => {
index++;
const nextEntry = getEntry(index);
if (nextEntry == null) return;
const timeDiff = nextEntry.time - entry.time;
emitEntryEvent(entry);
setTimeout(processEntry, timeDiff, nextEntry, index);
};
processEntry(getEntry(0), 0);
这会发出当前条目,然后根据差异设置超时,直到下一个条目。
getEntry
可以从预填充数组中获取行,也可以根据索引单独获取行。在后一种情况下,只有两行数据只会同时存在于内存中。
终于成功了! setTimeout 结果是答案,并结合 Lucas S 的输入。这就是我最终得到的结果:
const EventEmitter = require('events');
const fs = require('fs');
const readable = fs.createReadStream("./data/2018-07-18_1509log.json", {
encoding: 'utf8',
fd: null
});
function read_next_line() {
var chunk;
var line = '';
// While this is a thing we can do, assign chunk
while ((chunk = readable.read(1)) !== null) {
// If chunk is a newline character, return the line
if (chunk === '\n'){
return JSON.parse(line);
} else {
line += chunk;
}
}
return false;
}
var lines = [];
var nextline;
const processEntry = () => {
// If lines is empty, read a line
if (lines.length === 0) lines.push(read_next_line());
// Quit here if we've reached the last line
if ((nextline = read_next_line()) == false) return true;
// Else push the just read line into our array
lines.push(nextline);
// Get the time difference in milliseconds
var delay = Number(lines[1].time - lines[0].time) * 1000;
// Remove the first line
lines.shift();
module.exports.emit('data', lines[0]);
// Repeat after the calculated delay
setTimeout(processEntry, delay);
}
var ready_to_start = false;
// When the stream becomes readable, allow starting
readable.on('readable', function() {
ready_to_start = true;
});
module.exports = new EventEmitter;
module.exports.start = function() {
if (ready_to_start) processEntry();
if (!ready_to_start) return false;
}