filepointerの内容をistreamで受け取る

プログラム中で実行したコマンドの出力をストリームで受け取りたい.
というのも,プログラム中でxzcatした出力を標準入力からきたもののように処理したいためである.

とりあえずpopen()を使うことで,出力内容をファイルディスクリプタとして受け取ることができることはわかった.このまま,fgetsなどを利用して読み込んでもいいのだが,出来れば標準入力みたいに受け取りたいのである.というわけで色々調べたところ,同じようなことをやっておられる方がいた.

C++でpopenで開いたプロセスをistreamから読む - 饅頭日誌 改 〜となりの一茶鼓〜

まさに,自分がやりたかったことだ!というわけで早速参考にさせていただいた.
そのままのではなぜか動かなかったので,istreamのコンストラクタの部分は少し変えてある.

/*
 * fd_to_stream.cc
 */
#include <iostream>
#include <ext/stdio_filebuf.h>
#include <cstdlib>

int main()
{
  // popenでコマンド実行後の出力をfdで受け取る
  FILE *fp = popen("xzcat fd_to_stream.cc.xz", "r");

  // streambufを作成し,istreamのコンストラクタに渡す
  __gnu_cxx::stdio_filebuf<char> *p_fb = new __gnu_cxx::stdio_filebuf<char>(fp, std::ios_base::in);
  std::istream input(static_cast<std::streambuf *>(p_fb));

  // getlineでストリームからコマンド出力を受け取る
  std::string buffer;
  while(getline(input, buffer)){
    std::cout << "out > " << buffer << std::endl;
  }

  return 0;
}


上記ファイルをxz圧縮したものを読み込んでみる.
実行結果

out > /*
out > * fd_to_stream.cc
out > */
out > #include
out > #include
out > #include
out >
out > int main()
out > {
out > // popenでコマンド実行後の出力をfdで受け取る
out > FILE *fp = popen("xzcat fd_to_stream.cc.xz", "r");
out >
out > // streambufを作成し,istreamのコンストラクタに渡す
out > __gnu_cxx::stdio_filebuf *p_fb = new __gnu_cxx::stdio_filebuf(fp, std::ios_base::in);
out > std::istream input(static_cast(p_fb));
out >
out > // getlineでストリームからコマンド出力を受け取る
out > std::string buffer;
out > while(getline(input, buffer)){
out > std::cout << "out > " << buffer << std::endl;
out > }
out >
out > return 0;
out > }

ちゃんと読めている.
よかったー.