当运行命令以及如何逐行捕获输出时,popen会经历什么时间间隔?
可以说我在下面有这段代码,我用它来运行一个简单的命令,如ls
,并假设输出为100
行。当运行命令以及如何逐行捕获输出时,popen会经历什么时间间隔?
当我们在下面的代码中做cout << buff
时,输出是逐字节地,逐位地或逐行地进行流传输还是逐行传输?
可以说我们要打印new_line!
因为我们正在流式传输,所以每一个新行的字符串结束cout<<buff
。我们该怎么做?
我想在这while
循环中,我们应该有一些应该检查,它只是流(或即将流)\n
到我们的stringstream output
,它决定之后(或之前)做一些它流进输出。
最初,我只作为数据结构它来存储,所以我只需要知道如何检查\n
因为我们bufferring并往哪里放,增加了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
。有关更详细的解释,请参阅here。
否则,请使用系统提供的任何设施读取FILE*
中的一行。如果你真的找不到这样的设施(这将是非常令人惊讶的),那么最糟糕的是,你总是可以使用this approach。 fgets
也是一个很好的解决方案,只要你考虑缓冲区大小的限制,如果需要的话可以自己做更多的缓冲(检查the doc,一切都被解释了)。
你必须记住的事情是,popen
只是返回FILE*
所以任何可以在标准文件上工作的东西也适用于你的情况。网络上有很多例子。
现在对于你的问题的“时间间隔”部分,恐怕没有多大意义。首先,它取决于外部命令向标准输出打印新数据的时间间隔。无论如何,只要外部命令写入它,您就可以在程序中读取它。
就像fget
与stdio。它会一直等到EOF(程序关闭)或缓冲区被填满。
因此,while循环的每次迭代将获得512字节的数据,或者程序终止或stdio关闭后的剩余部分。
你可以用这样的小程序测试:
#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);
}
谢谢你的例子,它真的帮助:) – Logan 2013-03-01 23:12:42
管,因为它涉及的(直到它到达一些实施限制,可能无法轻易找到将缓存中的数据 - 但它是“充足的” - 在这个点上,当ls
写入它时,管道将“阻塞”,因此ls
将停止),除非您更快地读出它,在这种情况下,您的线程将被阻塞。如果您输出到屏幕上,则很可能您的输出会限制速度。
这样的管道不是“块状”或“线路缓冲”的 - 它只是一根管道 - 任何一端放在另一端。当然,如果“文件管理”的内部请求4000字节,则在读取操作完成之前可能需要等到4000字节通过另一端。但最有可能的是fgets
的内部是理智的,不会一次要求大量的数据。
谢谢,我不确定'getline()'是否可以工作,谢谢你的清除! – Logan 2013-03-01 22:59:53