1

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

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

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

我在想,在那个while循环中,我们应该有一些东西来检查它是否刚刚流入(或即将流入)\n到我们的 stringstreamoutput中,并且它决定在流入输出之后(或之前)做一些事情。

最初我将把它变成数据结构来存储,所以我只需要知道如何在缓冲时检查,\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;
}
4

3 回答 3

1

如果您使用 GNU libc,那么您可以getline()使用fgets. 有关更详细的说明,请参见此处。

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

您必须记住的是,popen只返回 aFILE*所以任何适用于标准文件的东西也适用于您的情况。网络上的例子很多。


现在对于您问题的“间隔”部分,恐怕没有什么意义。首先,这取决于外部命令将新数据打印到标准输出的时间间隔。无论如何,只要外部命令写入它,您就可以在程序中读取它。

于 2013-03-01T22:44:25.737 回答
1

就像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);
}
于 2013-03-01T22:44:37.690 回答
1

管道将在数据进入时对其进行缓冲(直到它达到一些可能不容易找到的实现限制 - 但它是“大量的” - 此时管道将在ls写入时“阻塞”,因此ls会停止),除非你读得更快,在这种情况下你的线程会阻塞。如果您要输出到屏幕,您的输出可能会限制速率。

这样的管道不是“块”或“行缓冲”——它只是一个管道——放在一端的任何东西都会从另一端出来。当然,如果“文件管理”的内部要求 4000 字节,则可能要等到 4000 字节在另一端通过后,才能完成读取操作。但很可能内部结构fgets是健全的,不会一次要求大量数据。

于 2013-03-01T22:50:21.483 回答