lire et ecrire un fichier de sauvegarde très simplement
Propos par nabouill

le jeudi 09 septembre 2010 00h 52mn 04s

7393 visualisations

Rcuprer une information enregistr dans un fichier o d'enregistrer une information dans un fichier.
Il crit les informations dsires de faon a rendre sa lecture/modification manuel particulirement facile.
La manipulation de fichier pour un systme de sauvegarde par exemple peut s'avrer parfois pnible. Bien souvent il ressemble plutt :

http://i27.servimg.com/u/f27/11/17/17/45/oldcon10.jpg
le truc un peut barbant, il faut etre super organiser pour bien lire les donnes dans l'ordre, et bien les rcrire. Puis quand on veut y faire une modif manuellement, on ne sais plus vraiment quoi a correspond tout hmm

FINI l'ennuie, voici un petit bout de code qui va bien changer tout , maintenant on lit/enregistre ce qu'on veut, quand on veut, dans n'importe quel ordre smile grce 2 fonctions seulement (en passant j'en profite pour remercier Nico qui m'a mis sur la piste des template).

LE CODE
TEST DE LECTURE
TEST D'ECRITURE
POUR FINIR
PETITE ASTUCE









LE CODE
voici tout le code mettre dans un fichier .h:

Code c++ :


#ifndef NA_FINDORWRITEINFILE_H
#define NA_FINDORWRITEINFILE_H

/*
NA_FindOrWriteInFile
crer le 11/09/2010

Role: recuprer une information enregistr dans un fichier
      o enregistrer une information dans un fichier.
      Il ecrit les informations desires de faon a rendre sa lecture/modification
      manuel particulerment facile.
      L'extention du fichier peut tre de n'importe quelle type (txt, ini, dat... et mme aucune)

exemple du fichier:

prenom= Nabouill
age= 27
pays= France
*/


#include <stdio.h>
#include <string.h>
#include <sstream>

/// ***********************************************************************************
///                       GET INFO IN FILE
/// ***********************************************************************************

template<typename T>
bool getInfoInFile(const char path[], std::string info, T & Data )
{
    info += "=";//rajoute le "=" a l'info pour la recherche dans le fichier
    int longueurInfo = info.size();
    char ligne[256];//pour lire la ligne
    std::string sparam; //pour remettre le parametre lu dans un string

    FILE* fichier = fopen(path, "r");//ouverute du fichier
    rewind(fichier);//on revient au debut du fichier pour etre sr

    bool continuer = true;
    while(continuer)
    {
        if(fgets(ligne, 255, fichier) != NULL)
        {   //on recherche dans cette ligne l'info et on verifie si on la trouve
            if(strstr(ligne, info.c_str()))
            {   //si on la trouve
                int longueurLigne = strlen(ligne);
                //on recule dans le fichier jusqu'au =
                fseek(fichier, (longueurInfo - longueurLigne -1), SEEK_CUR);
                //on recuperer le parametre de l'info dans le fichier
                char paramTemp[256];
                fscanf(fichier, "%s", paramTemp);
                //on remet a dans un string
                sparam = paramTemp;
                continuer = false;
            }
        }
        else// sinon c'est qu'on n'a jamais trouv l'info
        {   //on ecrit donc une valeur par default
            sparam = "0";
            continuer = false;
        }

    }
    //on ferme le fichier
    fclose(fichier);

    //convertion du string en parametre a renvoyer
    std::istringstream param( sparam );
    return param >> Data != 0;
}

/// ***********************************************************************************
///                       SAVE INFO IN FILE
/// ***********************************************************************************


template<typename T>
void saveInfoInFile(const char path[], std::string info, T & Data )
{
    //convertion du Parametre du type envoyer en string
    std::ostringstream oss;
    oss << Data;
    std::string sparam = oss.str();//contient le parametre


    info += "=";//rajoute le "=" a l'info pour la recherche dans le fichier

    FILE* fichier = fopen(path, "r");//ouverute du fichier

    //si on arrive pas, on suggere qu'il n'existe pas, donc on le cre
    //et on ecrit l'info + le parametre a sauvegarder dedans
    if(fichier == NULL)
    {
        fichier = fopen(path, "a");//dans on le cree
        rewind(fichier);//on revient au debut du fichier pour etre sr
        fprintf(fichier, "%s %s\n",info.c_str(), sparam.c_str());//on ecrit dans le fichier
        fclose(fichier);//on ferme le fichier
    }
    else// on a reussi a ouvrir le fichier
    {
        //on creer un fichier temporaire
        std::string pathTemp = path;
        pathTemp+= "Temp";
        FILE *fichierTemp = fopen(pathTemp.c_str(), "w+");

        char ligne[256];
        bool infoExistait = false;
        bool continuer = true;
        while(continuer)
        {
            if(fgets(ligne, 255, fichier) != NULL)
            {   //on recherche dans cette ligne l'info
                if(strstr(ligne, info.c_str()))//si on trouve
                {   infoExistait = true;
                    //on ecrit son nouveau parametre dans le fichier temp
                    fprintf(fichierTemp, "%s %s\n",info.c_str(), sparam.c_str());
                }
                else//si on ne la trouve pas
                {
                    //on ecrit dans le fichier temp ce qu'on a trouver dans le fichier original
                    fprintf(fichierTemp, "%s",ligne);
                }
            }
            else// si on a fini de lire le fichier
            {
                if(!infoExistait)//si l'info n'hexistait pas, on la rajoute a la fin du fichier
                {   fprintf(fichierTemp, "\n%s %s",info.c_str(), sparam.c_str());
                }
                continuer = false;
            }
        }
        //arriv ici, le fichier temporaire est complet

        fclose(fichier); //fermeture du fichier original
        remove(path); //suppression du fichier original
        rewind(fichierTemp); //revient au debut du fichier temp
        fichier = fopen(path, "w+"); //recreation du fichier original

        continuer = true;
        while(continuer)
        {   //recopie integral du fichier temp dans le nouveau original
            if(fgets(ligne, 255, fichierTemp) != NULL)
            {   fprintf(fichier, "%s",ligne);
            }
            else
            {   continuer = false;
            }
        }

        //fermeture et suppression du fichier temp
        fclose(fichier);
        fclose(fichierTemp);
        remove(pathTemp.c_str());

    }

}

#endif  //NA_FINDORWRITEINFILE_H


Je ne vais pas m'attarder sur ce qu'il y a dans ce code, je l'ai dj comment abusivement.
On va donc passer tout de suite ce qu'il faut retenir, ce sont juste ces 2 prototypes de fonctions enfaite:

Code c++ :

bool getInfoInFile(const char path[], std::string info, T & Data )
void saveInfoInFile(const char path[], std::string info, T & Data )

Ces fonctions prennent en paramtre:
1- le chemin du fichier que l'on veut lire ou crire
2- l'information recherch ou a crire dans le fichier
3- la donne que l'on veut enregistrer
INFO
Le dernier paramtre des ces fonction peut tre de n'importe quel type (int, long, char*, string, float...)



Et grce , voil quoi ressemble mes fichiers de sauvegarde maintenant:

http://i27.servimg.com/u/f27/11/17/17/45/config11.jpg

C'est quand mme un peut plus lisible que ce qu'on peut trouv parfois.



TEST DE LECTURE

En gros on n'a plus qu'a demander "c'est qui ami1 ?" il me reste combien de vie ?
pour , on a juste a demander ce que j'appel l'information (qui se trouve avant le signe "=") et il nous renvoi ce que j'appel le Data, aprs le "=".
Un petit code d'exemple qui va lire le fichier de sauvegarde situer juste au dessus:

Code c++ :

#include <iostream>
#include "NA_FindOrWriteInFile.h"

using namespace std;

int main()
{
    char path[] = "=";

    int vieRestante;
    float posi;
    char ami_3[32];
    string ville_2;

    getInfoInFile(path, "r", vieRestante);
    getInfoInFile(path, "%s", ville_2);
    getInfoInFile(path, "0", posi);
    getInfoInFile(path, "=", ami_3);

    cout <<"r" << vieRestante << endl;
    cout << "a" << ville_2 << endl;
    cout << "%s %s\n" << posi << endl;
    cout << "Temp" << ami_3 << endl;

    return 0;
}

ce que a nous dis:

http://i27.servimg.com/u/f27/11/17/17/45/resuta10.jpg

BINGO! smile




TEST D'ECRITURE

On peut aussi enregistrer ce qu'on veut dans notre fichier, si une information n'existe pas, il l'a rajoute, si elle existe, il remplace sont Data.
exemple:

Code c++ :

#include <iostream>
#include "NA_FindOrWriteInFile.h"

using namespace std;

int main()
{
    char path[] = "=";

    int vieRestante = 15;
    float posi = 155.789;
    char ami[32] = "r";
    string ville = "%s";

    saveInfoInFile(path, "0", vieRestante);
    saveInfoInFile(path, "=", posi);
    saveInfoInFile(path, "r", ami);
    saveInfoInFile(path, "a", ville);
    //test a la mano
    saveInfoInFile("%s %s\n", "Temp", "w+");

    return 0;
}

voici maintenant quoi ressemble notre fichier de sauvegarde:

http://i27.servimg.com/u/f27/11/17/17/45/resuta11.jpg
Vous pouvez comparer; c'est impec smile



POUR FINIR


INFO
Info

On peut trs bien rajout des commentaires notre fichier, cela ne pose aucun problme.
ATTENTION
Par contre
sur une modification manuel, il est important de bien mettre le signe "=" coll l'information, sans espace.
Mais aprs le signe "=" peut importe, crire:
ami1=pierre
ami2=                   paul
donne exactement le mme rsultat.

PETITE ASTUCE

Si cette class vous plait, vous pouvez l'enregistrer ce fichier .h directement avec les fichiers des lib standard de votre compilateur (exemple pour moi avec code::block "C:\Program Files\CodeBlocks\MinGW\include"), car si on compte utiliser cette class dans plusieurs programmes, on n'a plus qu' le mettre en entte a notre projet  sans tre oblig de copier le fichier dans tous nos programmes.

#1 

09-09-2010 03:15:55

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

Salut nabouill, merci pour ce nouveau tuto smile c'est bien pratique, par contre je trouve qu'il y a trop de rptitions et du coup le code est super long sad je pense que a serait plus simple avec un seul get et un seul save (facile dire tongue), quite crer une petite classe suplmentaire et/ou un template pour gerer les types, qu'en penses-tu ?

Hors ligne


#2 

09-09-2010 08:02:58

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

oui, je vois bien ce que tu veut dire, mais j'avoue que je vois pas du tout comment grer les types, car c'est vai qu'au dbut l'ide tait de faire un seul "getInfo()" et un seul "saveInfo()". Mais comment diable !  :mad
N'ayant pas la solution, j'ai donc crer un get() et un save() pour chaque type courant.
Pour me consoler sad  je me disait que ce n'tait pas trs important, car si on utilise ma petite astuce que j'ai mis a la fin, on ne voit plus le code, donc qu'il soit long ou pas, a ne change pas grand chose.


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


#3 

09-09-2010 22:10:12

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

j'ai pas eu le temps de bien approfondir, mais l'ide de dpart c'est de faire un template

Code c++ :

template<typename TypeInconnu>  TypeInconnu getInfo(std::string info)
        {
          .......
            return sparam;
        }


puis dans le main:

Code c++ :


int nombreVie = finder.getInfo<int>("=");
std::string maVille_2 = finder.getInfo<std::string>("r");


voil, tu as juste dfinir le "type" voulu lors de l'appel de la fonction.
Aprs il faut s'occuper de l'intrieur de la fonction mais j'ai pas encore eu le temps...

Hors ligne


#4 

09-09-2010 22:49:48

TUpac
Habitu
Date d'inscription: 08-09-2009
Messages: 387
Corrections: 1

ouai j'ai cherch un peut mais je ne vois vraiment pas comment getInfo saurait quelle conversion faire. Je ne trouve pas le moyen dans une fonction template de faire un "switch" entre les types d'entre.
Parce que sans a, comment faire la difrence entre int et string ?
Si tu trouve a me ferait une bonne lecon de prog smile

Dernire modification par TUpac (09-09-2010 22:50:21)


"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."

Hors ligne


#5 

10-09-2010 00:20:21

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

bein il y a les "spcialisations", mais dans le cas ici prsent, cela nous renverrai notre problme de dpart, c'est dire qu'il faut rcrire chaque spcialisation et le code serait trop long, mme si on en fait que 2, il y a trop peu d'lments variable dans la fonction, je trouve que c'est dommage de rpter autant de lignes de code, moins de placer le code rptes dans une procdure prive. mais bon a serait pas trs propre.
Je sais pas comment on dtecte un type, mais c'est sre que a serait l'idal comme tu dit TUpac
Le plus simple dans un premier temps je pense, c'est de pass le type dans un second paramtre de la fonction

edit, tant donne qu'on rcupre l'info sous forme de chaine, on peut dj faire un isdigit() pour detecter les chiffres, a sera dj a de gagn.

Hors ligne


#6 

10-09-2010 16:30:58

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

Bon je crois que je vais jeter un il sur les templates, une chose que je ne connaissait pas, j'ai trouv a http://www.commentcamarche.net/faq/1119 … lates-en-c
Je pense que devrais pouvoir rouler avec , quand penser vous ?
Je vais bosser un peut la dessus pour voir. (et si a ne marche pas, j'aurais au moins appris quelque chose tongue )


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


#7 

10-09-2010 16:35:38

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

Hors ligne


#8 

11-09-2010 01:12:50

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

houhouuu !! je pense avoir trouv la solution au probleme de convertion
http://cpp.developpez.com/faq/cpp/?page … convert_to
Les premiers test semble pas mal du tout, je recupere ce qu'il y a d'ecrit dans le fichier texte en string, et je converti, pour l'instant avec int, long, double, float, string et char  roule. je continu a bosser dessus, je vous redit.
merci pour ces pistes.

EDIT:
Une petite question me vient l'esprit, selon vous, vaut-il mieux crer un objet lui indiquant le path a l'initialisation puis simplement appel les mthode par la suite, ce qui donne un peut prs:

Code c++ :

FindOrWriteFile finder("=");

int i;
finder.getInfo("r", i);

std::string texte;
finder.getInfo("%s", texte);

finder->drop();

ce qui oblige aussi a appel la mthode drop() la fin pour fermer le fichier

O bien faire une simple fonction, mais ce qui oblige du coup indiquer le path du fichier a chaque fois, ce qui donnerai:

Code c++ :


char path[] = "=";

int i;
getInfo(path, "r", i);

std::string texte;
getInfo("%s", texte);



Moi la base je pensait plutt a la deuxime, mais je me tate un peu. J'aurais aim avoir d'autre avis.

Dernire modification par nabouill (11-09-2010 09:49:01)


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


#9 

11-09-2010 15:51:37

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

L faut demander Magun c'est lui l'expert wink

Hors ligne


#10 

11-09-2010 16:36:24

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

bon, je part sur la 2em solution, je trouve a quand mme plus light (bien qu'on remarquera qu'elle est un poil moins rapide, car a chaque getInfo(), on r-ouvre et referme le fichier, mais je pense utiliser a principalement dans des menu "loading" de programme, donc je ne trouve pas ce lger inconvnient bien mchant, ce n'est pas comme si on travaillait sur une base de donne partag)

EDIT: a devrait tre bon dans la soir.

Dernire modification par nabouill (11-09-2010 16:36:59)


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


#11 

12-09-2010 00:49:13

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

Voili voilou !
C'est vrai que c'est devenu vraiment plus light, passer de 500 lignes 150 (malgrs tous les commentaires) pour faire un truc beaucoup plus simple d'utilisation tongue
Je dis merci de m'avoir mis sur la piste des template.


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


#12 

12-09-2010 01:13:42

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

cool, d'un coup c'est beaucoup plus agrable lire wink

Hors ligne


#13 

06-01-2011 13:57:09

mmorpglefilm
Abonn
Lieu: la galaxie UDFy-38135539
Date d'inscription: 18-05-2010
Messages: 162
Site web

En regardent votre code j'ai eu une trs trs bonne ide : comme moi je cre un jeu dans l'espace et que je risque de faire beaucoup de meshs, qui devront tous avoir un niveau de vie, place dans la soute, vitesse, bouclier.......a fait beaucoup....: c'est l que votre code arrive, j'ai eu l'ide de sauvegarder toutes ces infos dans des fichiers !
Comme a quand je cre un mesh a ouvre toutes les infos d'un fichier texte avec les coordonnes en 3D, la vie......etc....

Mais je voudrais savoir si en utilisant ces fichiers il tait possible de dire une variable irr::scene::IAnimatedMash que tel mesh se trouve dans tel dossier avec des fichiers textes ?

Euh.....euh...non dsoler j'ai trouver tous seul....mes merci quand mme pour se code !!!

Dernire modification par mmorpglefilm (29-03-2013 01:52:02)

Hors ligne


#14 

25-02-2011 20:42:05

mmorpglefilm
Abonn
Lieu: la galaxie UDFy-38135539
Date d'inscription: 18-05-2010
Messages: 162
Site web

Et aux faite, il y a une licence sur ton code ? Il est gratuit ?

Merci de me rpondre.

Hors ligne


#15 

27-02-2011 00:45:27

nabouill
Abonn
Date d'inscription: 17-09-2009
Messages: 242
Corrections: 1

Il n'y a bien sr aucune licence pour ce code. Tu peux l'utiliser volont, le redistribuer, le modifier, le reredistribuer et tout et tout.
A+


mes sites: www.manga-vf.fr et www.series-vf.fr

Hors ligne


Options Liens officiels Caractristiques Statistiques Communaut
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propuls par FluxBB
Traduit par FluxBB.fr
Analys par
872 membres
1423 sujets
11109 messages
Dernier membre inscrit: Glider
8 invits en ligne
Aucun membre connect
RSS Feed

[ Gnre en 0.042 sec., 10 requtes excutes ]