在运行命令时,popen的时间间隔是多少,以及如何逐行捕获输出



假设我有下面这段代码,我用它来运行一个简单的命令,比如ls,我们假设输出是100行长。

当我们在下面的代码中执行cout << buff时,输出是逐字节、逐位还是逐行流式传输,或者间隔是多少?

假设我们想在流式传输cout<<buff时打印每个新行的new_line!字符串结尾。我们怎样才能做到呢?

我认为在while循环中,我们应该有一些东西应该检查它刚刚将(或即将流)n流到我们的stringstream output中,并且它决定在它流到输出之后(或之前)做一些事情。

最初,我将把它放入数据结构中存储,所以我只需要知道如何检查n,因为我们正在进行缓冲,以及在哪里放置添加new_line!的函数或我想做的任何事情。

代码如下:

#include <iostream>
#include <stdio.h>
using namespace std;
// imaginary 
// stringstream output;

int main() {
    FILE *in;
    char buff[512];
    if(!(in = popen("ls -sail", "r"))){
        return 1;
    }
    while(fgets(buff, sizeof(buff), in)!=NULL){
            // output << buff;
            // if there is a new line
            // output << "new_line!";
        cout << buff;
    }
    pclose(in);
    return 0;
}

如果您使用GNU libc,那么您可以使用getline()而不是fgets

否则,使用系统提供的任何工具从FILE*中读取一行。如果您确实找不到这样的设施(这将是非常令人惊讶的),那么最坏的情况是您总是可以使用这种方法。fgets也是一个很好的解决方案,如果你考虑到缓冲区大小限制,并在需要时自己做一些更多的缓冲(检查文档,一切都有解释)。

你要记住的是,popen只是返回一个FILE*,所以任何可以在标准文件上工作的东西也可以在你的情况下工作。网络上有很多这样的例子。


现在你的问题的"间隔"部分,恐怕它没有什么意义。首先,它取决于外部命令将新数据打印到标准输出的时间间隔。在任何情况下,只要外部命令写入它,就可以在程序中读取它。

管道将缓冲数据,因为它进来(直到它达到一些实现限制,可能不容易找到-但它是"充足的"-在这一点上,管道将"阻塞"当ls写它,所以ls将停止),除非你读它更快,在这种情况下,你的线程将阻塞。如果您要输出到屏幕上,那么您的输出可能会限制速率。

这样的管道不是"块"或"行缓冲"的-它只是一个管道-无论在一端放入什么,都会从另一端输出。当然,如果"文件管理"的内部请求4000字节,那么在读取操作完成之前,可能需要在另一端使用4000字节。但最有可能的是,fgets的内部是健全的,不会要求一次大量的数据。

就像fget与stdio一样。它将等待,直到EOF(程序已经关闭)或直到缓冲区被填满。

因此,while循环的每次迭代要么获得512字节的数据,要么在程序终止或关闭studio后获得剩余的数据。

你可以用一个像这样的小程序来测试:

#include <thread>
#include <chrono>
#include <iostream>
int main() {
    std::cout << "hello" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << " world" << std::endl;
}

你会注意到,尽管休眠时间很长,它仍然会尝试读取512字节,并在stdout关闭时关闭。

要以符合标准的方式管理实际的分块,您可以使用std::fgetc并构建自己的缓冲区。

http://en.cppreference.com/w/cpp/io/c/fgetc

你自己的getline可能看起来像这样:

std::string get_line(FILE* f) {
    char c;
    std::string out;
    while(c=std::fgetc(f)!='n' && c!=EOF) {
         out+=c;
    }
    out+='n';
    return out;
}

//...
//usage
while(!std::feof(in)) {
    cout << get_line(in);
}

相关内容

  • 没有找到相关文章

最新更新