我有一个这样的程序:

#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对象中,即刷新转换为在管道上进行写操作。

10-02 15:18