【问题标题】:Writing popen() output to a file将 popen() 输出写入文件
【发布时间】:2011-01-20 10:23:56
【问题描述】:

我一直在尝试从 c++ 调用另一个程序,并将该程序的 stout 保存到一个文本文件中。 popen() 似乎是合适的函数,但将其保存到文本文件不起作用。

      ofstream delaunayfile;
    delaunayfile.open ("triangulation/delaunayedpoints.txt");
      FILE *fp;
      fp = popen("qdelaunay < triangulation/rawpoints.txt", "r");
    delaunayfile << fp;
    delaunayfile.close();

有什么帮助吗?提前致谢!

【问题讨论】:

    标签: c++ system popen


    【解决方案1】:

    您不能将FILE* 直接写入流。它会写入一个内存地址而不是实际的文件内容,因此它不会给你想要的结果。

    理想的解决方案是从ifstream 读取并写入您的ofstream,但无法从FILE* 构造ifstream。

    但是,我们可以扩展 streambuf 类,使其在 FILE* 上工作,然后将其传递给 istream。快速搜索发现有人已经实现了它,并正确命名为popen_streambuf。见this specific answer。

    您的代码将如下所示:

    std::ofstream output("triangulation/delaunayedpoints.txt");
    popen_streambuf popen_buf;
    if (popen_buf.open("qdelaunay < triangulation/rawpoints.txt", "r") == NULL) {
        std::cerr << "Failed to popen." << std::endl;
        return;
    }
    char buffer[256];
    std::istream input(&popen_buf);
    while (input.read(buffer, 256)) {
        output << buffer;
    }
    output.close();
    

    正如 cmets 中的 Simon Richter 所指出的,有一个 operator&lt;&lt; 接受 streambuf 并将数据写入 ostream 直到到达 EOF。这样,代码将被简化为:

    std::ofstream output("triangulation/delaunayedpoints.txt");
    popen_streambuf popen_buf;
    if (popen_buf.open("qdelaunay < triangulation/rawpoints.txt", "r") == NULL) {
        std::cerr << "Failed to popen." << std::endl;
        return;
    }
    output << &popen_buf;
    output.close();
    

    【讨论】:

    • 请注意,在您的示例中,您还可以使用output &lt;&lt; &amp;popen_buf; 复制数据,因为有一个operator&lt;&lt;(std::ostream &amp;, std::streambuf *);。
    • @Simon Richter:哦,我完全错过了!更新以提及您的建议。谢谢!
    【解决方案2】:

    有两种方法可以做到这一点:简单的方法

    int rc = system("qdelaunay < triangulation/rawpoints.txt >triangulation/delaunayedpoints.txt");
    

    还有更复杂的方法,使用 fork()、dup2() 和 execve(),后者在系统上没有安装 shell 解释器的情况下工作。鉴于这看起来你正在做计算工作,我怀疑这不是一个嵌入式系统,所以你可以假设一个工作外壳。

    【讨论】:

      【解决方案3】:

      popen 打开一个管道,但我不知道您可以通过这种方式将其流式传输到 delaunayfile。

      当然,如果你能做到这一点,它会从管道中读取直到它完成,那将是非常好的。

      在管道上检查数据的常规方法是使用 select()。我找到了一个有用的链接http://codenewbie.com/forums/threads/2908-Using-std-fstream-in-a-pipe,它集成了管道和 fstream,它可以帮助你实现你想要的。

      在这种情况下,尽管您只想将输出写入文件,但为什么不将进程的输出重定向到它而不是管道呢?管道的目的是进程间通信,但您的进程似乎没有将它从其他进程接收到的数据用于任何实际目的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-20
        • 1970-01-01
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-10
        相关资源
        最近更新 更多