1. #1
    Membre actif
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    mai 2010
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 27
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : mai 2010
    Messages : 292
    Points : 285
    Points
    285

    Par défaut Ajouter du contenu au début d'un fichier

    Bonjour,

    je voudrais savoir s'il est possible d'ajouter du contenu au début d'un fichier texte.
    En effet, dans mon programme je crée un fichier texte contenant un grand nombre de valeurs décimales (le fichier final fait plusieurs centaines de Mo, jusqu'à 1,5Go environ). Pour cela j'utilise la classe QFile ainsi qu'un QTextStream. J'écris les valeurs dans le fichier par groupe de 1000 lignes au fur et à mesure qu'elles sont calculées. Au passage je calcule des statistiques globales sur les valeurs du fichier.

    Je voudrais ensuite ajouter ces valeurs de statistiques comme entête du fichier. J'ai essayé avec le QTextStream et seek(0) mais cela ne fonctionne pas (le contenu ajouté écrase l'ancien contenu). J'ai malheureusement l'impression que ce n'est pas possible car on ne peut pas décaler comme ça l'ensemble du contenu d'un fichier. Mais vu la taille du fichier cela prendrait beaucoup trop de temps de créer un nouveau fichier avec l'entête puis d'y copier le contenu du premier fichier.
    Voyez-vous une solution possible?

    Merci d'avance!

  2. #2
    Membre expert
    Inscrit en
    mars 2005
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 027
    Points : 3 026
    Points
    3 026

    Par défaut

    Écrire au début d'un fichier (en préservant son contenu, s'entend) est une opération impossible sur la plupart des systèmes de fichiers, et lorsqu'une API expose une telle opération c'est qu'elle en dérobe les rouages à l'utilisateur. Il faut mettre en cache au moins la même quantité de données que celle qu'on veut y ajouter.

    S'il s'agit de la principale opération que tu as a réaliser sur ton fichier, peut-être faudrait-il revoir la structure de données sous-jacente ?

  3. #3
    Membre actif
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    mai 2010
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 27
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : mai 2010
    Messages : 292
    Points : 285
    Points
    285

    Par défaut

    Merci de ta réponse!
    Malheureusement je ne vois pas comment faire autrement car le format des données m'est imposé (entête puis valeurs), je suis obligée de m'occuper des valeurs en premier (car j'ai besoin des infos calculées pour renseigner l'entête) et obligée de les écrire au fur et à mesure car cela prend beaucoup de mémoire.
    Je vais essayer de trouver une autre solution!

    Merci de ton aide

  4. #4
    Membre expert
    Inscrit en
    mars 2005
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 027
    Points : 3 026
    Points
    3 026

    Par défaut

    Pourquoi ne pas écrire ces informations d'en-tête dans un fichier séparé ?

  5. #5
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2010
    Messages
    173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mai 2010
    Messages : 173
    Points : 275
    Points
    275

    Par défaut

    Bonjour,
    Si le format de l'en tête est fixe, il est peut-être possible de "réservé" l'espace de l'en tête en y plaçant des valeurs bidons qui seront ensuite écrasé lors de l'écriture de l'en-tête.
    Sinon un autre possibilité serait de garder les valeurs en mémoire et de ne les écrire dans le fichier qu'une fois l'en-tête écrite.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    Consultant informatique
    Inscrit en
    octobre 2004
    Messages
    10 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : octobre 2004
    Messages : 10 517
    Points : 23 010
    Points
    23 010

    Par défaut

    Salut,

    De manière générale, tu dois vraiment te dire qu'écrire dans un fichier, c'est exactement pareil à essayer de graver du texte dans le marbre (hé oui, on est de retour à l'époque de Jules Cesar sur ce coup là :p)

    Si tu te trompes lors de l'écriture, ou si tu veux rajouter quelque chose ailleurs que APRES le dernier caractère déjà écrit, tu n'as pas vraiment d'autre choix que de "casser la pierre", et recommencer tout le travail.

    Pour palier à ce problème, tu as deux possibilités :

    Soit, tu charge directement l'intégralité de ton fichier en mémoire, puis tu fais ton frichtis, tous les calculs et toutes les modifications que tu veux, avant de réécrire l'intégralité du fichier, et de toutes les modifications que tu y as apportées.

    L'énorme avantage de cette manière de travailler, c'est les accès (que ce soit en lecture ou en écriture) sont les plus lents que l'on puisse touver sur un ordinateur (si on excepte les accès à des informations au travers d'un réseau, quel qu'il soit). Surtout si tu arrête la lecture pour quelque raison que ce soit:

    le plateau du disque dur tournant en permanence, il y a de fortes chances pour que, quand tu reprendra la lecture, tu doive encore attendre que la tête de lecture se retrouve "au bon endroit" pour te donner la prochaine information qui doit être lue (*)

    Le principal inconvénient de cette pratique, c'est qu'elle nécessite un espace disponible en mémoire de taille au moins équivalente à la taille du fichier que tu veux traiter. Mais bon, on peut encore assez facilement estimer que n'importe quel ordinateur datant d'après 2010 devrait supporter de te fournir 1.5 Gb de mémoire

    La deuxième solution résoudra sans doute le problème de mémoire que la première pourrait poser. Mais tu risques de voir ton temps de traitement multiplié par 100, si pas plus, à cause, justement, des accès au disque dur. En plus, tu peux te dire que, ce que tu gagnera en utilisation de la mémoire, tu la perdra en utilisation d'espace disque, car il n'y a rien à faire: il faudra bien stocker les données quelques part!

    L'idée consiste, effectivement, à lire le fichier "par tranche", comme tu en as eu le pressentiment (tu peux d'ailleurs envisager d'écrire bien plus de 1000 lignes...), mais, au lieu de tout écrire dans un fichier "unique", d'écrire à chaque fois toutes ces données dans un "fichier temporaires", dans le sens où les 1000 première lignes seraient écrite dans fichier_0001, les 1000 suivantes dans fichier_0002 et ainsi de suite, si bien que les données allant de la ligne 50 000 à la ligne 51 000 se trouveraient sans doute dans fichier_0050.

    De cette manière, la seule chose que tu gardes en mémoire, c'est... les données de statistiques que tu as calculé (ou peu s'en faut).

    Une fois que tu as terminé tous tes calculs, il ne te restera "plus qu'à" créer le fichier "final", dans lequel tu mettrait en premier ... tes données statistiques avant d'y ajouter le contenu des fichiers temporaires, dans l'ordre dans lequel ils ont été créés.

    Une fois que cela sera fait, tu pourras supprimer les fichiers temporaires sans te poser de question.

    (*) bon, il est vrai que je ne parle pas d'un disque dur SSD sur ce coup... De toutes manières, on les utilise plus souvent comme disque "système" que comme disque "données"...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre actif
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    mai 2010
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 27
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : mai 2010
    Messages : 292
    Points : 285
    Points
    285

    Par défaut

    Merci de ces réponses instructives,
    j'ai finalement pu faire ce que je souhaite en utilisant la solution de Gojir4 c'est-à-dire remplir l'entête avec des valeurs bidon et les remplacer ensuite.
    Après effectivement, la solution de koala01 de charger l'intégralité du fichier en mémoire pour tout réécrire avec l'entête aurait sans doute très bien fonctionné aussi, c'est vrai que le PC peut largement supporter 1,5 GB de mémoire.

    Voici mon code (version simplifiée):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    // Creation du fichier de données
    QFile dataFile("myDataFile.txt");
    if(dataFile.open(QFile::WriteOnly | QFile::Text))
    {
            // Ecriture de l'entete (version initiale avec valeurs bidon "0000000000", "1111111111" et "2222222222")
    	QTextStream myFileStream(&dataFile);
    	QStringList entete;
            entete.append("#Premiere ligne d'entete");
            entete.append("#");
            entete.append("#Moy1=0000000000;Moy2=1111111111;Moy3=2222222222");
            entete.append("#");
            myFileStream << entete.join("\n") << endl;
     
            // Fonction de calcul de donnees, ajoutées au fur et à mesure dans le fichier + calcul des valeurs moy1, moy2 et moy3
            float moy1, moy2, moy3;
            computeData(myFileStream, moy1, moy2, moy3);
            dataFile.close(); // Fermeture du fichier
     
            // Modification de l'entete avec les valeurs moyennes calculees
            QFile dataFile2("myDataFile.txt");
            if(dataFile2.open(QFile::ReadWrite | QFile::Text)) // Bien ouvrir en mode ReadWrite et non WriteOnly
            {
                int lineLength = entete[2].count(); // Longueur de la chaine a modifier
     
                // On remplace les "000", "111" et "222" par les valeurs de moy1, moy2 et moy3
                QString newLine = entete[2].replace("0000000000", QString::number(moy1, 'f', 3));
                newLine = newLine.replace("1111111111", QString::number(moy2, 'f', 3));
                newLine = newLine.replace("2222222222", QString::number(moy3, 'f', 3));
     
                // Les valeurs prennent normalement moins de caractères que les valeurs bidon précédentes, on complete la fin de chaine
                // avec des espaces pour conserver la meme longueur
                while(newLine.count() < lineLength)
                   newLine += " ";
     
                // Remplacement dans le fichier si les deux chaines (la precedente et la nouvelle) ont bien le meme nombre de caracteres
                if(newLine.count() == lineLength)
                {
                    entete[2] = newLine; // La QStringList "entete" contient maintenant la version correcte de l'entete complet
     
                    QTextStream myFileStream2(&dataFile2);
                    myFileStream2.seek(0);                                // On se place au debut du fichier pour ecraser l'ancien entete
                    for(int i = 0; i < entete.size(); i++)
                        myFileStream2 << entete[i] << endl;
                }
                dataFile2.close();
            }
    C'est ce qui m'a semblé le plus simple à faire et cela n'a pas d'impact visible sur la durée d'exécution de mon programme.
    Merci à tous pour votre aide!

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 21/10/2008, 10h46
  2. ajout de texte en début de fichier
    Par youp_db dans le forum Windows
    Réponses: 1
    Dernier message: 21/02/2008, 17h50
  3. Ajouter du texte au début d'un fichier
    Par ned-flanders dans le forum Fichiers
    Réponses: 6
    Dernier message: 03/12/2007, 00h54
  4. Réponses: 19
    Dernier message: 10/07/2007, 09h24
  5. Ajouter le contenu d'un fichier dans un autre
    Par persia dans le forum Fichiers
    Réponses: 3
    Dernier message: 12/03/2007, 09h37

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