2009-11-05 15 views
8

假設我「POPEN」的可執行文件,我得到的回報一個FILE*。此外,假設我想這個文件「連接」到istream對象更容易處理,有沒有辦法做到這一點?FILE *和istream:連接兩個?

回答

4

沒有標準的方式,但如果你想有一個快速的解決方案,你可以得到的fileno()的文件描述符,然後使用約祖蒂斯fdstream。可能會有類似的努力,但我在遙遠的過去使用它,它工作得很好。如果沒有別的,它應該是一個非常好的地圖來實現你自己的。

1

確實有辦法,實施您自己的istream,可以從FILE*構建。

如果你問是否有做到這一點,那麼沒有一個標準的方式。

13

您可以通過派生的std :: basic_streambuf或std ::流緩衝類脫身。
沿着這些線:

#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 2011-01-20 10:53:33