2009-12-24 63 views
4

我需要爲我的程序的輸入做這樣的事情:的IStream(升壓::輸入輸出流)或文件

stream input; 
if (decompressed) 
    input.open(filepath); 
else { 
    file_descriptor=_popen("decompressor "+filepath,"r"); 
    input.open(file_descriptor); 
} 
input.read(...) 
... 

我可以看到一個解決方案 - 在這兩種情況下使用_popen和剛纔複製的文件標準輸出,如果它已經解壓縮,但這看起來不太優雅。

有趣的是這與C相比有多困難 - 我猜標準庫錯過了它。現在我迷失在神祕的boost :: iostreams文檔中。如果有人知道如何,示例代碼會很棒。

+0

文件描述符是特定操作系統的一項功能。既然如此,便攜式語言如C++通常不會指定處理它們的函數。您可能會感到驚訝的是,C標準沒有指定任何文件描述符函數。 – 2009-12-24 11:08:33

+0

一切都是操作系統的一個功能,包括文件和進程。我已經接受了這個特殊的功能被忽略了C++標準,我願意使用boost或其他任何能夠使我無法使用fread重寫整個類的東西。 – graw 2009-12-24 11:21:51

+0

是的,很有趣的是,面嚮對象語言與程序語言有何不同。不同的是,一旦你理解OO,與程序相比,更容易得到正確的結果。 – 2009-12-24 17:35:26

回答

5

這是你以後:

#include <cstdio> 
#include <string> 
#include <iostream> 
#include <boost/iostreams/device/file_descriptor.hpp> 
#include <boost/iostreams/stream.hpp> 

namespace io = boost::iostreams; 

int main() 
{ 
    bool flag = false; 

    FILE* handle = 0; 
    if (flag) 
    { 
     handle = _popen("dir", "r"); 
    } 
    else 
    { 
     handle = fopen ("main.cpp", "r"); 
    } 

    io::stream_buffer<io::file_descriptor_source> fpstream (fileno(handle)); 
    std::istream in (&fpstream); 

    std::string line; 
    while (in) 
    { 
     std::getline (in, line); 
     std::cout << line << std::endl; 
    } 

    return 0; 
} 
+0

啊,我沒有正確思考,是的,這解決了謝謝! – graw 2009-12-24 23:24:41

+2

較新版本的boost已棄用只有'fd'的構造函數。相反,您需要將'boost :: iostreams :: never_close_handle'或'boost :: iostreams :: close_handle'作爲強制的第二個參數傳遞給構造函數。 – Flexo 2013-09-21 13:20:09

0

添加到喬恩 - 漢森的回答,這裏有一個簡單的例子演示如何使用file_descriptor_source與管道。

如何打造:

g++ -m32 -DBOOST_IOSTREAMS_NO_LIB -isystem ${BOOST_PATH}/include \ 
    ${BOOST_SRC_PATH}/libs/iostreams/src/file_descriptor.cpp blah.cc -o blah 

代碼:

#include <fcntl.h> 
#include <stdio.h> 

#include <boost/iostreams/device/file_descriptor.hpp> 
#include <boost/iostreams/stream.hpp> 

int main(int argc, char* argv[]) { 
    // if you just do 'using namespace...', there's a 
    // namespace collision with the global 'write' 
    // function used in the child 
    namespace io = boost::iostreams; 

    int pipefd[] = {0,0}; 
    pipe(pipefd, 0); // If you use O_NONBLOCK, you'll have to 
         // add some extra checks to the loop so 
         // it will wait until the child is finished. 

    if(0 == fork()) { 
    // child 
    close(pipefd[0]); // read handle 
    dup2(pipefd[1], FILENO_STDOUT); 
    printf("This\nis\na\ntest\nto\nmake sure that\nit\nis\working as expected.\n"); 
    return 0; // ya ya, shoot me ;p 
    } 

    // parent 

    close(pipefd[1]); // write handle 

    char *buff = new char[1024]; 
    memset(buff, 0, 1024); 

    io::stream<io::file_descriptor_source> fds(
    io::file_descriptor_source(pipefd[0], io::never_close_handle)); 

    // this should work with std::getline as well 
    while( fds.getline(buff, 1024) 
     && fds.gcount() > 0 // this condition is not enough if you use 
          // O_NONBLOCK; it should only bail if this 
          // is false AND the child has exited 
     ) { 
    printf("%s,", buff); 
    } 

    printf("\n"); 
}