2009-11-05 13 views
8

Giả sử tôi "mở" một tệp thực thi, tôi nhận được một số FILE*. Hơn nữa, giả sử tôi muốn "kết nối" tệp này với đối tượng istream để xử lý dễ dàng hơn, có cách nào để thực hiện việc này không?TẬP_TIN * và istream: kết nối hai?

Trả lời

4

Không có cách tiêu chuẩn nhưng nếu bạn muốn có giải pháp nhanh chóng, bạn có thể lấy bộ mô tả tệp bằng fileno() và sau đó sử dụng Josuttis 'fdstream. Có thể có những nỗ lực tương tự xung quanh nhưng tôi đã sử dụng nó trong quá khứ xa xôi và nó hoạt động tốt. Nếu không có gì khác nó phải là một bản đồ rất tốt để thực hiện của riêng bạn.

1

Chắc chắn có một cách, triển khai istream của riêng bạn có thể được xây dựng từ FILE*.

Nếu bạn hỏi liệu có cách nào tiêu chuẩn để thực hiện việc này hay không, thì không.

13

Bạn có thể thoát khỏi bằng cách bắt đầu các lớp std :: basic_streambuf hoặc std :: streambuf.
Điều gì đó dọc theo các dòng sau:

#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 Khá hữu ích! Làm tốt :-) – jweyrich