2012-09-09 5 views
3

Je suis en train de coder un projet Android avec un composant NDK C++ et j'ai un fichier qui nécessite beaucoup d'analyse. Le NDK me permet seulement d'obtenir un pointeur FILE * pour le fichier auquel j'ai affaire, pas un ifstream qui a quelques fonctions de commodité supplémentaires associées. Est-il possible de convertir un FICHIER * (cstdio) en ifstream (iostream)?Convertir FICHIER * en ifstream C++, Android NDK

Répondre

3

Notez qu'il n'y a pas moyen de récupérer un std::ifstream, mais vous peut obtenir std::istream.

Bien que n'étant pas une partie de la norme C++, parfois std::basic_filebuf expose une extension via un constructor which takes std::FILE *.

basic_filebuf(FILE *fp, char_type *buf = 0, 
       streamsize n = /* default size */); 

Constructs an object of class basic_filebuf , initializing the base class with basic_streambuf<charT,traits>() . It then calls open(fp, buf, n) .

La façon dont vous devez utiliser est la suivante ...

FILE *pf = ...; /* e.g. fopen("/etc/passwd", "r") */ 
std::filebuf buf(pf); 
std::istream stream(&buf); 

Maintenant, si cette extension n'est pas disponible, alors je crains qu'il n'y ait pas grand-chose que vous pouvez faire autre que d'essayer de implémentez votre propre std::streambuf qui implémente le travail requis.

+0

J'ai essayé d'utiliser la deuxième partie de votre code mais je me suis erreur: pas de fonction concordante pour l'appel à 'std :: basic_filebuf :: basic_filebuf (FILE * &)' ----- code: FICHIER * fp = fopen ("./ Output_BinaryImage.pgm", "r"); std :: filebuf buf (fp); std :: flux istream (&buf); – inblueswithu

+0

@inblueswithu a lu mon message en entier - J'adresse cette erreur C'est une extension non-standard de 'std :: filebuf' – oldrinb

5

En général, vous pouvez pas convertir un FILE* en std::ifstream. Cependant, ce n'est pas vraiment nécessaire de toute façon: il est raisonnable de créer un tampon de flux personnalisé qui peut être utilisé pour initialiser un std::istream. L'utilisation d'un std::istream devrait suffire car les fonctionnalités supplémentaires fournies par std::ifstream ne facilitent pas vraiment l'analyse. Tant que vous n'avez pas besoin d'utiliser la recherche, créer un tampon de flux pour lire à partir d'un FILE* est vraiment simple. Il suffit Redéfinition de la fonction std::streambuf::underflow():

class stdiobuf 
    : std::streambuf 
{ 
private: 
    FILE* d_file; 
    char d_buffer[8192]; 
public: 
    stdiobuf(FILE* file): d_file(file) {} 
    ~stdiobuf() { if (this->d_file) fclose(this->d_file); } 
    int underflow() { 
     if (this->gptr() == this->egptr() && this->d_file) { 
      size_t size = fread(this->d_file, 8192); 
      this->setg(this->d_buffer, this->d_buffer, this->d_buffer + size); 
     } 
     return this->gptr() == this->egptr() 
      ? traits_type::eof() 
      : traits_type::to_int_type(*this->gptr()); 
    } 
}; 

Tout ce qui reste est d'initialiser un std::istream d'utiliser un stdiobuf:

stdiobuf  sbuf(fopen(...)); 
std::istream in(&sbuf); 

Je viens tapé dans le code ci-dessus et je ne peux pas encore Essaye le. Cependant, la base devrait être correcte bien qu'il puisse y avoir des types et peut-être même un petit défaut.

+1

Cela nécessite une petite modification Le troisième argument 'taille' dans this-> setg() devrait être 'this-> d_buffer + size' –

+0

@BostonWalker: corrigé Merci! –