2009-12-24 3 views
4

que je dois faire quelque chose comme ça pour mon entrée de programme:istream de file_descriptor_source (boost :: iostreams) ou un fichier

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

Je peux voir une solution - utiliser _popen dans les deux cas et il suffit de copier le fichier à stdout si c'est déjà décompressé, mais cela ne semble pas très élégant. Drôle combien cela est difficile par rapport à C - Je suppose que la bibliothèque standard l'a manqué. Maintenant, je suis perdu dans la documentation cryptic boost :: iostreams. Exemple de code serait génial si quelqu'un sait comment.

+0

descripteurs de fichiers sont une caractéristique des systèmes d'exploitation spécifiques. Dans ce cas, les langages portables comme C++ ne spécifient normalement pas les fonctions pour les traiter. Cela peut vous surprendre de savoir que le standard C ne spécifie aucune fonction de descripteur de fichier non plus. –

+0

Tout est une fonctionnalité des systèmes d'exploitation, y compris les fichiers et les processus. J'ai accepté que cette fonctionnalité particulière a été omise de la norme C++ et je suis prêt à utiliser boost ou toute autre chose qui va me sauver de réécrire toute la classe en utilisant Fread. – graw

+0

Oui, c'est drôle à quel point un langage OO est différent d'un langage procédural. La différence est une fois que vous comprenez OO, il est beaucoup plus facile d'avoir raison par rapport à la procédure. –

Répondre

5

Est-ce que vous êtes après:

#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

Ahhh je ne pensais pas correctement, oui cela résout merci! – graw

+2

Les nouvelles versions de boost ont déprécié le constructeur qui ne prend qu'un 'fd'. Au lieu de cela, vous devez passer un de 'boost :: iostreams :: never_close_handle' ou' boost :: iostreams :: close_handle' comme deuxième argument obligatoire pour le constructeur. – Flexo

0

Ajout à la réponse de jon-hanson, voici un exemple simple montrant comment utiliser file_descriptor_source avec un tuyau.

Comment construire:

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

Le code:

#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"); 
} 
Questions connexes