IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Gerer un fichier de plusieurs Gigaoctets avec un fstream


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Points : 725
    Points
    725
    Par défaut Gerer un fichier de plusieurs Gigaoctets avec un fstream
    Bonjour

    Utilisant un ifstream je veux obtenir la taille d'un fichier, classique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    is.seekg (0, ios::end); //is est un ifstream
    taille =is.tellg(); //taille est un long int
    is.seekg (0, ios::beg);
    sauf que ca ne marche pas avec un gros fichier exemple:
    un fichier de 4.7Go donne 800 mo environ ce qui n'est pas normal.
    Alors comment resoudre ce probleme?

    raphchar
    Raphchar.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Selon ton OS, long int peut être sur 32 bits. Utilises, si ton compilateur l'a, int64_t pour la transformation en valeur intégrale.

  3. #3
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Points : 725
    Points
    725
    Par défaut
    Ca ne fonctionne pas (j'ai utilisé un __int64), et même résultat !
    Raphchar.

  4. #4
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,

    Tu es peut-être sur un vieux compilateur dont la biblio iostream standard ne savait pas gérer les fichiers de 4go ?

    Pour en avoir le cœur net, que donne un sizeof(std::streamsize) ?
    Si c'est 8 octets (64 bits) c'est bon, mais sinon tu es coincé.
    Par exemple dans mes souvenirs la biblio iostream de Visual Studio a été adapté entièrement pour supporter les fichiers de plus de 4Go aux alentours de VS2005/2008

  5. #5
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Points : 725
    Points
    725
    Par défaut
    J'ai vérifié, c'est bien 8, et j'utilise VS2010, bizarre !!
    Raphchar.

  6. #6
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par raphchar Voir le message
    J'ai vérifié, c'est bien 8, et j'utilise VS2010, bizarre !!
    Je viens de vérifier avec VS2010.
    Le problème est en effet présent... La biblio iostream de VS2010 est buggée avec des fichiers > 2Go

    Confirmation ici :
    https://connect.microsoft.com/Visual...n-x64-platform

    c'est franchement inacceptable qu'un bug pareil se soit retrouvé dans une release officielle.
    Microsoft n'a donc pas de jeu de test s'assurant que fstream fonctionne correctement avec des grands fichiers !!? C'est assez perturbant.
    Donc raphchar, il me semble qu'il n'y a pas d'autre solution que de faire comme dans la FAQ C en utilisant GetFileAttributesEx...

  7. #7
    Membre éclairé
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Juin 2008
    Messages
    522
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 522
    Points : 725
    Points
    725
    Par défaut
    Bon, je suis fixé alors !!
    La meilleurs solution est de changer de compilateur.
    Raphchar.

  8. #8
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Elle n'est pas buggée ; elle fait exactement ce qu'on lui dit de faire.

    C'est à dire que tellg renvoie un objet du type streampos, qui est implicitement converti en int (quand on vous dit que les conversions implicite, c'est mal !) ; et l'int, sur une plateforme 32 bits, c'est 32 bits. Que tu le convertissent en int64_t ou pas derrirère, ça ne changera rien : le standard dit "int".

    Le bug, si bug il y a, est dans le standard lui-même, pas dans la librairie (et on peut se demander à juste titre pourquoi est-ce que le standard considère qu'une position de stream est nécessairement un int ; ça, c'est un bug).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  9. #9
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Je ne suis pas d'accord, si je comprends bien le standard, le type renvoyé par tellg (pos_type) est implementation-defined. AHMA justement pour laisser toute latitude aux implémentateurs de choisir un type assez grand pour la manipulation de fichier.

    Et il y a bien un bug dans la STL de VS2010, que ce soit sur platforme 32/64 bits, bug du à un mauvais cast:
    streampos contains a 32-bit "conversion state", but also contains two 64-bit positions. The problem was that a 32-bit cast was hiding in a macro. We've fixed the cast, so large file support should work correctly now (regardless of x86/x64 platform)
    Car si l'on remonte tout au bout de la définition de pos_type, on s’aperçoit que pos_type est en fait un typedef d'une struct nommée fpos, qui possède l'opérateur de cast suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     __CLR_OR_THIS_CALL operator streamoff() const
       {	// return offset
         return ((streamoff)(_Myoff + _FPOSOFF(_Fpos)));
       }
    Sous VS2010 la macro _FPOSOFF vaut #define _FPOSOFF(fp) ((long)(fp)).
    Avec VS2011 preview la macro a été corrigé et vaut maintenant #define _FPOSOFF(fp) ((long long)(fp))

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Je ne suis pas d'accord, si je comprends bien le standard, le type renvoyé par tellg (pos_type) est implementation-defined. AHMA justement pour laisser toute latitude aux implémentateurs de choisir un type assez grand pour la manipulation de fichier.
    Pas tout à fait : le standard dit que le type est implementation-defined, mais qu'il doit se comporter comme std::fpos<S>, ou S est implementation-defined lui aussi (avec quand même quelques requirement).

    C'est le type fpos<S> qui est implicitement casté en int (et il a aussi un constructeur non implicite à partir d'un int).

    Bref, le standard demande à ce que le résultat de l'expression stream.tellg(); soit transformé de manière implicite en int (j'ai relu ça 5 fois parce que je ne le croyais pas). cf. la table des requirements de fpos<> (je ne me rappelle plus le §).

    A noter que ça n'a pas changé en C++11.

    Moi, personnellement, je pense que c'est un bug du standard. Je ne vois pas pourquoi le standard force le type int. Il devrait forcé un type intégral signé implementation-defined capable de représenter toute position dans un fichier. Je ne vois pas l'intérêt de force le type int.

    Par contre, ce a quoi tu fais référence est effectivement un bug de l'implémentation de la C++SL de VS2010, mais ça concerne un autre point. Car le même tableau défini aussi les conversions vers et à partir des types streamoff et streamsize. Or ces deux types doivent pouvoir représenter la taille maximale d'un fichier sur la plateforme, sous une forme signée (donc probablement un ssize_t ; ou long long dans le nouveau standard). Le cast en long sur une plateforme 32 bits est clairement mauvais.

    Un autre problème se pose alors, parce ni streamoff, ni streamsize ne sont clairement défini. Par exemple, on ne sait pas s'ils possède un opérateur de cast (et vers quel type). Ces deux types contienent des états et rien dans le standard ne dit comment récupérer ces états. Du coup, le problème reste plus ou moins entier
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  11. #11
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Donc au final, hors code initial, pour avoir la vrai taille d'un gros fichier en C++ on a quoi?


    1. Visiblement ya une fonction dans boost donc si on a boost sous la main on peut appeler file_size() : http://www.boost.org/doc/libs/1_48_0...html#file_size

    Est-ce que quelqu'un a déjà vérifié que ça marche sur les gros fichiers?

    2. Parcourir un filestream jusqu'à la fin en comptant les octets?
    3. Une autre solution?

    Le sujet est interessant parceque si il n'y a aucun moyen correcte d'obtenir la taille d'un gros fichier en C++, on est pas dans la merde...

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Pas tout à fait : le standard dit que le type est implementation-defined, mais qu'il doit se comporter comme std::fpos<S>, ou S est implementation-defined lui aussi (avec quand même quelques requirement).

    C'est le type fpos<S> qui est implicitement casté en int (et il a aussi un constructeur non implicite à partir d'un int).
    Je n'ai pas vu ce cast en int (même s'il existe bien la construction depuis int, ce qui peut être bien pratique, surtout quand le int vaut 0, ainsi que la construction depuis un stream_off)
    Citation Envoyé par Emmanuel Deloget Voir le message

    Bref, le standard demande à ce que le résultat de l'expression stream.tellg(); soit transformé de manière implicite en int (j'ai relu ça 5 fois parce que je ne le croyais pas). cf. la table des requirements de fpos<> (je ne me rappelle plus le §).
    Table 127 en C++11
    Citation Envoyé par Emmanuel Deloget Voir le message
    Moi, personnellement, je pense que c'est un bug du standard. Je ne vois pas pourquoi le standard force le type int. Il devrait forcé un type intégral signé implementation-defined capable de représenter toute position dans un fichier. Je ne vois pas l'intérêt de force le type int.
    C'est bien ce qui est indiqué en 27.1 pour stream_off (figure 7):
    signed integer type sufficient for O/S maximum file size

    Sachant que fpos est entièrement convertible bidirectionnellement en stream_off
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Je n'ai pas vu ce cast en int (même s'il existe bien la construction depuis int, ce qui peut être bien pratique, surtout quand le int vaut 0, ainsi que la construction depuis un stream_off)
    Dingue ça. Je suis sûr de l'avoir vu quelque part, et je n'arrive pas à remettre la main dessus.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Mêmes fichiers sur plusieurs domaines, avec paramètres ?
    Par charade dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 02/07/2013, 12h01
  2. Réponses: 1
    Dernier message: 05/12/2008, 09h18
  3. (D7) Attacher plusieurs fichiers dans un mail avec mapifile
    Par mario9 dans le forum Composants VCL
    Réponses: 2
    Dernier message: 18/06/2008, 21h07
  4. Réponses: 2
    Dernier message: 12/05/2006, 23h59
  5. Réponses: 2
    Dernier message: 26/04/2006, 15h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo