2009-11-05 4 views
8

はI "popenの" 実行可能ファイルを仮定し、私はお返しにFILE*を取得します。さらに、私は簡単に処理するためにistreamオブジェクトにこのファイルを「接続」したいと仮定し、これを行う方法はありますか?FILE *とistream:2つを接続しますか?

答えて

4

標準的な方法はありませんが、簡単な解決策が必要な場合は、ファイル記述子をfileno()で取得し、Josuttisのfdstreamを使用してください。同じような努力があるかもしれませんが、私は遠い過去にこれを使用し、うまくいきました。それ以外の場合は、自分自身を実装するための非常に良いマップでなければなりません。

1

確かな方法があります、FILE*から構築することができるistream独自のものを実装します。

あなたがいない、その後、これを行うための標準的な方法があるかどうかを求めている場合。

13

あなたはSTD :: basic_streambufかのstd :: streambufのクラスを派生させて逃げることができます。
これらの行に何か:

#include <stdio.h> 
#include <iostream> 

#define BUFFER_SIZE  1024 

class popen_streambuf : public std::streambuf { 
public: 
    popen_streambuf() : fp(NULL) { 
    } 
    ~popen_streambuf() { 
     close(); 
    } 
    popen_streambuf *open(const char *command, const char *mode) { 
     fp = popen(command, mode); 
     if (fp == NULL) 
      return NULL; 
     buffer = new char_type[BUFFER_SIZE]; 
     // It's good to check because exceptions can be disabled 
     if (buffer == NULL) { 
      close(); 
      return NULL; 
     } 
     setg(buffer, buffer, buffer); 
     return this; 
    } 
    void close() { 
     if (fp != NULL) { 
      pclose(fp); 
      fp = NULL; 
     } 
    } 
    std::streamsize xsgetn(char_type *ptr, std::streamsize n) { 
     std::streamsize got = showmanyc(); 
     if (n <= got) { 
      memcpy(ptr, gptr(), n * sizeof(char_type)); 
      gbump(n); 
      return n; 
     } 
     memcpy(ptr, gptr(), got * sizeof(char_type)); 
     gbump(got); 

     if (traits_type::eof() == underflow()) { 
      return got; 
     } 
     return (got + xsgetn(ptr + got, n - got)); 
    } 
    int_type underflow() { 
     if (gptr() == 0) { 
      return traits_type::eof(); 
     } 
     if (gptr() < egptr()) { 
      return traits_type::to_int_type(*gptr()); 
     } 
     size_t len = fread(eback(), sizeof(char_type), BUFFER_SIZE, fp); 
     setg(eback(), eback(), eback() + (sizeof(char_type) * len)); 
     if (0 == len) { 
      return traits_type::eof(); 
     } 
     return traits_type::to_int_type(*gptr()); 
    } 
    std::streamsize showmanyc() { 
     if (gptr() == 0) { 
      return 0; 
     } 
     if (gptr() < egptr()) { 
      return egptr() - gptr(); 
     } 
     return 0; 
    } 
private: 
    FILE *fp; 
    char_type *buffer; 
}; 

int main(int argc, char *argv) 
{ 
    char c; 
    popen_streambuf sb; 
    std::istream is(&sb); 

    if (NULL == sb.open("ls -la", "r")) { 
     return 1; 
    } 

    while (is.read(&c, 1)) { 
     std::cout << c; 
    } 

    return 0; 
} 
+0

+1かなり便利です!よくやった :-) – jweyrich

関連する問題