来自file_descriptor_source(boost :: iostreams)或文件的istream

时间:2009-12-24 10:31:07

标签: c++ file boost stream iostream

我需要为我的程序输入做这样的事情:

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

我可以看到一个解决方案 - 在两种情况下都使用_popen,如果文件已经解压缩,只需将文件复制到stdout,但这似乎不太优雅。

与C相比有多么困难 - 我想标准库错过了它。现在我迷失在神秘的boost :: iostreams文档中。如果有人知道如何,示例代码会很棒。

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

添加到jon-hanson的回答中,这是一个简单的示例,演示了如何将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" );
}