我有一个这样的程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
for(int i = 0; i<3; i++){
printf("Cstdout:%d ", i);
fflush(stdout);
fprintf(stderr, "Cstderr:%d ", i);
fflush(stderr);
}
return 0;
}
该程序的输出为:Cstdout:0 Cstderr:0 Cstdout:1 Cstderr:1 Cstdout:2 Cstderr:2
我想使用如下的node.js脚本处理其输出:
var spawn = require('child_process').spawn,
ls = spawn('./io');
var Jstdout = 0, Jstderr = 0;
ls.stdout.on('data', function (data) {
console.log('Jstdout:' + Jstdout + ' ' + data);
++Jstdout;
});
ls.stderr.on('data', function (data) {
console.log('Jstderr:' + Jstderr + ' ' + data);
++Jstderr;
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});
该脚本的输出为:
Jstdout:0 Cstdout:0 Cstdout:1 Cstdout:
Jstderr:0 Cstderr:0 Cstderr:1 Cstderr:2
子进程已退出,代码为0
但我想要类似的东西:
Jstdout:0 Cstdout:0
Jstderr:0 Cstderr:0
Jstdout:1 Cstdout:1
Jstderr:1 Cstderr:1
Jstdout:2 Cstdout:2
Jstderr:2 Cstderr:2
子进程已退出,代码为0
我猜您的C ++程序填充缓冲区的速度比node.js读取缓冲区的速度快。如果让您的子进程在每次迭代后等待约100ms,会发生什么情况? –德克·霍斯滕
德克·霍斯滕(Dirk Horsten)的说法是正确的:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
for(int i = 0; i<3; i++){
printf("Cstdout:%d ", i);
fflush(stdout);
sleep (1);
fprintf(stderr, "Cstderr:%d ", i);
fflush(stderr);
sleep (1);
}
return 0;
}
这段代码将产生我想要的输出,但是我想格式化我尚未编写的程序的输出,并且我不容易在这些程序中放置延迟。
例如,我想为valgrind的输出着色,但是valgrind的输出同时使用stdout和stderr。当我尝试这样做时,文本块的位置会更改。
在下一个脚本中,我尝试将输出着色为程序蓝色,将valgrind输出着色为红色:
var spawn = require('child_process').spawn,
ls = spawn('valgrind', [process.argv[2]]);
ls.stdout.on('data', function (data) {
console.log('\033[1;34m' + data + '\033[0m');
});
ls.stderr.on('data', function (data) {
console.log('\033[1;31m' + data + '\033[0m');
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});
最佳答案
至少使用常规方法是不可能的。
子进程输出通过管道接收。管道是OS提供的对象。内部有一个缓冲区;管道上的每个write()都会追加到缓冲区。各个块的边界不会保留-如果写入器足够快,它将在读取器有机会读取任何内容之前设法将多个项目排队。阅读器将收到当前可用的任何数据;如果有多个块被缓冲,它可以一次全部接收。
当然,这个问题使通过管道交换消息变得更加困难。为了能够拆分连接的消息,必须有一些指示消息结束的地方(例如:换行符终止消息[some nodejs context])。
关于冲洗的注意事项。在C中,FILE对象具有自己的缓冲区。刷新将缓冲区内容传输到底层OS对象中,即刷新转换为在管道上进行写操作。