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++Builder Discussion :

fichier txt : tellg() ne me retourne pas de bonnes valeurs


Sujet :

C++Builder

  1. #1
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut fichier txt : tellg() ne me retourne pas de bonnes valeurs
    bonjour,

    Je suis sous WindowsXP et je travaille avec BorlandC++ 6 Professionnal.

    J'ai un sérieux souci avec un fichier texte.

    Plus précisément avec des \n à la position 4096 et 4097 de ce fichier texte. A cause de ces caractères, la fonction tellg() ne me retourne pas de bonnes valeurs.

    Pour être sûr que cela ne venait pas de mon fichier, je génère un fichier txt avec un contenu aléatoire et en imposant un \n lorsque j'arrive au 4096 et 4097 caractères. J'utilise les codes ASCII compris entre 32 (espace) inclus et 127 (supprimer) exclus.

    J'ai mis dans ma fenêtre 1 TStringGrid, un bouton (BtnOuvrir) et un composant OpenDialog (OpenDialog1).


    Code c++ : 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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
    TfFichier *fFichier;
     
    //---------------------------------------------------------------------------
    __fastcall TfFichier::TfFichier(TComponent* Owner)
        : TForm(Owner)
    {
        StringGrid1->ColWidths[0] = 500;
        StringGrid1->ColWidths[1] = 40;
        StringGrid1->ColWidths[2] = 40;
     
        GenereFichier();
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TfFichier::BtnQuitterClick(TObject *Sender)
    {
        Close();
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TfFichier::GenereFichier()
    {
      int i, n;
      int min, max;
      min = 0;
      max = 127;
     
      srand(time(NULL));
      ofstream Fichier("texte.txt", ios::out);
     
     
      for (n=0; n<5000; n++)
      {
        i = (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
        if (n==4095 || n==4097 || n==4096)
        {
            Fichier<<endl;
        }
        else
        {  
            if (i>=32 && i<127)
            {
                    Fichier<<char(i);
            }
            else
            {
                Fichier<<endl;
            }
        }
     
        //Fichier.flush();
      }
     
      Fichier.close();
     
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TfFichier::BtnOuvrir1Click(TObject *Sender)
    {
        AnsiString nom, valeur;
        char buffer[4097];
        int n, i;
        unsigned char data;
     
        if (OpenDialog1->Execute())
        {
            nom = OpenDialog1->FileName;
            this->Repaint();
     
            Label1->Caption = nom;
            StringGrid1->Cols[0]->Clear();
            StringGrid1->Cols[1]->Clear();
            StringGrid1->Cols[2]->Clear();
     
            StringGrid1->RowCount = 2;
     
            ifstream Fichier(nom.c_str());
     
            n = 0;
            i = 1;
            while (!Fichier.eof() && Fichier.good())
            {
     
                Fichier.getline(buffer, sizeof(buffer), '\n');
     
                n = n + strlen(buffer) + 2;
     
                StringGrid1->Cells[0][i] = buffer;
                StringGrid1->Cells[1][i] = IntToStr(n);
                StringGrid1->Cells[2][i] =  IntToStr(Fichier.tellg());
     
     
                i++;
                StringGrid1->RowCount ++;
            }
     
            Fichier.close();
        }
     
    }


    n'oubliez pas d'inclure
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #include <fstream.h>
    #include <time.h>

    pour la fonction random et pour les ifstream et ofstream.

    ------------------------
    Dans le second RichEdit il y a 2 colonnes de chiffres :
    - le premier chiffre est la somme des longueur des chaines récupérées (j'ai ajouté 2 pour tenir compte du \n en fin de ligne) ;
    - le second chiffre est la valeur retournée par tellg().


    Regardez les 2 colonnes de valeurs dans le RichEdit2 : il y a un écart de 1 au moins jusqu'au 4096ème caractère entre la valeur de gauche et la valeur de droite.

    Si vous faites un fichier plus petit (moins de 4096 caractères dans la fonction GenereFichier), le problème ne se pose plus ou si vous supprimez ce test
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        if (n==4097 || n==4096) // j'impose un retour chariot ici
            Fichier<<endl;
    plus de problème non plus (à moins que la valeur de i soit inférieure à 32 à ce moment).


    Comment je peux corriger ce problème ? Sachant que je dois utiliser ifstream et ofstream.
    à vous


    [edit]
    j'ai modifié le code : j'utilise un TStringGrid au lieu des RichEdit : on peut plus facilement repérer les lignes qui posent problème (les valeurs de tellg() et calculées et le contenu de chaque ligne du fichier se trouvent sur la même ligne du TStringGrid).
    [/edit]

  2. #2
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    après plusieurs tests, je me demande si \n est le seul responsable (problème aléatoire )

  3. #3
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Salut Auteur
    Dans cette ligne je ferais un essai soit de decrementer soit d'incrementer la variable de comptage
    if (n==4097 || n==4096) // j'impose un retour chariot ici
    Fichier<<endl;
    else

  4. #4
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    Citation Envoyé par blondelle Voir le message
    Salut Auteur
    Dans cette ligne je ferais un essai soit de decrementer soit d'incrementer la variable de comptage
    c'est à dire ?

  5. #5
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Si j'ai bien compris tu ne veut soit comptabiliser soit tu ne veut pas comptabiliser les retours chariot quand tu passe dans le teste je pense que tu comptabilise.
    Il est peut etre possible dans un premier temps de mettre un compteur dans le teste pour compter ce que tu recoit et par comparaison tu verra si c'est la source de ton probleme.

  6. #6
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    La fonction genereFichier() impose un retour chariot à un endroit précis du fichier (4096 et 4097).

    Le problème est au moment de la lecture, les valeurs affichées sur une même ligne dans le second RichEdit sont parfois différentes (il faut lancer plusieurs fois le programme).

    Peut-être que le problème est au moment de la génération du fichier, mais où ??

  7. #7
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    La je seche aussi

  8. #8
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    visiblement c'est plus un problème C++, ce n'est pas spécifique à C++Builder :

    http://www.developpez.net/forums/sho...d.php?t=308579

  9. #9
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut fichier txt : tellg() ne me retourne pas de bonnes valeurs
    bonjour
    je pense que tellg() te donne la bonne valeur , c'est plutôt le calcul fait par le compilateur builder c++ 6 qui comptabilise un caractère pour \n alors qu'il met 0D + 0A soit deux caractères de plus il faut aussi voir si alignement des données se fait en B ,W ,DW ,QW
    dans ton exemple il faudrai éliminer le chr(10) et chr(13) pour éventuellement ne pas parasiter le résultat
    j'espère t'avoir aider de mes petites possibilités
    jpf

  10. #10
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    je pense que tellg() te donne la bonne valeur , c'est plutôt le calcul fait par le compilateur builder c++ 6 qui comptabilise un caractère pour \n
    Je pense aussi que cela vient du \n qui est mal "détecté". J'ai effectivement constaté 3 cas :
    1. il y a un décalage de 1 entre la position 0 et la position 4096, puis après 4096, il y a égalité entre la valeur calculée et la valeur retournée par tellg() ;
    2. ou il y a égalité entre la valeur calculée et la valeur retournée par tellg() entre la position 0 et la position 4096. Au delà de 4096 j'ai un décalage de 1 ;
    3. ou il y a toujours égalité entre la valeur calculée et la valeur retournée par tellg(). Dans ce cas pas de retour charriot à la position 4095 ou 4096.



    J'ai essayé avec :
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Fichier.getline(buffer, sizeof(buffer), '\n');
    Fichier.getline(buffer, sizeof(buffer), '\r');
    Fichier.getline(buffer, sizeof(buffer), (char)10);
    Fichier.getline(buffer, sizeof(buffer), (char)13);

    Visiblement le \r (ou (char)13) n'est pas détecté par getline.
    Toutefois en ouvrant le fichier texte en mode binaire, j'ai consaté que les caractères 10 et 13 sont bien présents dans le fichier texte.


    J'ai même changé les options du compilateur en essayant différents jeux d'instructions : 80386, Pentium, Pentium Pro ou i486, rien y fait (enfin presque : avec le jeu 80386, j'y ai cru un court moment ).



    Maintenant, je ne sais pas si c'est le compilateur qui est en cause car avec gcc par exemple, le problème persiste.


    il faut aussi voir si alignement des données se fait en B ,W ,DW ,QW
    euh.. c'est quoi l'alignement des données ?

    Je me demande même s'il n'y a pas un lien entre ce problème de \r\n (ou \n\r) à la position 4096 d'un fichier et la taille d'un secteur du disque (4096 octets également)

  11. #11
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    salut
    j'ai trouvé une piste dans un éditeur vexa j'ai vu qu'il y a une différence de 1 chaque fois qu'il y a un 20 (espace) avant 0D 0A
    ou un 20 après 0D 0A
    c'est a dire que si un buffer commence ou fini par un espace celui ci est éliminé
    peut être y a t'il une option dans compilateur qui oblige la fonction strlen () de prendre en compte ces espaces
    fjp

  12. #12
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    salut
    voila le code que j'ai changé il supprime les espaces de fins ou de début
    ca marche chez moi
    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
     
    //---------------------------------------------------------------------------
    //Génération de fichier avec contenu aléatoire
    // code ASCII des caractères entre 32 et 80
    void __fastcall TfFichier::GenereFichier()
    {
      int i, n;
      int min, max;
      min = 0;
      max = 80;
      bool premier=false;
      srand(time(NULL));
      ofstream Fichier("texte.txt");
     
    // fichier avec 5000 caractères
     
      for (n=0; n<5000; n++)
      {
        i = (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
        if (n==4097 || n==4096) // j'impose un retour chariot ici
        {
            Fichier<<char('.')<<endl;
            premier=true;
        }
        else
        {
            if (i<32) //32 code ASCII de l'espace
                {
                Fichier<<char('.')<<endl;   // retour chariot
                premier=true;
                }
             else
                {
                if (premier&&i==32);
                else
                {
                premier=false;
                Fichier<<char(i);  // caractè;re de code i (>=32)
                }
                }
        }
       }
    Fichier.close();
     
    }
    fjp

  13. #13
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    J'ai fait une mise à jour du code donné dans le premier post.

    le problème persiste

    J'ai généré des fichiers texte sans le caractère 32 (espace). J'ai toujours ce décalage, même si, il est vrai, le cas se produit plus rarement....

    Sauf si effectivement je n'ai pas de ligne vide ou si mon fichier ne commence pas par endl (a priori).


    La solution que tu m'apportes peut, sans doute, palier à ce problème, mais elle modifie la structure du fichier (je remplace un espace par un point, ou j'ajoute un point avant le retrour charriot).


    Mais ce que je n'arrive vraiment pas à comprendre c'est pourquoi à partir de la position 4096, l'équilibre se rétablit (il y a égalité entre la valeur retournée par tellg() et la valeur calculée).

  14. #14
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    salut
    j'ai essayé avec ton programe (stringgrid) et ca marche impec

  15. #15
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    voir printsceen
    Images attachées Images attachées  

  16. #16
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    j'ai généré deux fichiers texte :
    - le premier sans le caractère espace :
    Code c++ : 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
      for (n=0; n<5000; n++)
      {
        i = (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
        if (n==4095 || n==4097 || n==4096)
        {
            Fichier<<endl;
        }
        else
        { 
            if (i>32 && i<127)
            {
                    Fichier<<char(i);
            }
            else
            {
                Fichier<<endl;
            }
        }
      }
    - le second avec le caractère espace :
    Code c++ : 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
      for (n=0; n<5000; n++)
      {
        i = (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
        if (n==4095 || n==4097 || n==4096)
        {
            Fichier<<endl;
        }
        else
        { 
            if (i>=32 && i<127)
            {
                    Fichier<<char(i);
            }
            else
            {
                Fichier<<endl;
            }
        }
      }

    en pièces jointes les résulats obtenus : j'ai ce décalage qui disparait on ne sait comment après la position 4096

  17. #17
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    salut
    dans ce cas je ne vois qu'un effet de bord sur un des octets concernés
    essaye avec 4095 4097 4099
    soit avec 4095 96 97 dans l'ordre croissant
    a propos avec quelle bécane travailles-tu
    chez moi pas de décalage ni avant ni après
    c'est peut être du à une option de c++ 6
    fjp

  18. #18
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    c'est peut être du à une option de c++ 6
    laquelle ?

    J'ai déjà essayé certaines options du compilo :

    Citation Envoyé par Auteur Voir le message
    J'ai même changé les options du compilateur en essayant différents jeux d'instructions : 80386, Pentium, Pentium Pro ou i486, rien y fait

    Maintenant, je ne sais pas si c'est le compilateur qui est en cause car avec gcc par exemple, le problème persiste.
    J'ai un pentium IV. Avec un Athlon le problème est le même...

  19. #19
    fjp
    fjp est déconnecté
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 30
    Points : 28
    Points
    28
    Par défaut
    salut

    j'ai changé le \n par un \0 dans l'écriture et la lecture du ficher texte
    et j'ai fait n = n + strlen(buffer)+1 ; au lieu de deux ce qui est logique
    l'égalité deuxième colonne et troisième est la même tout le temps

    néanmoins je me pose la questions , pourquoi vouloir avoir une égalité dans ton programme , car même si tu cherches une occurrence dans un fichier son début sera le tellg () et si tu veux la remplacer tu devra chercher par un seekp() ,
    a moins de vouloir faire une indexation propriétaire et encore !!!!!

    fjp

  20. #20
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 650
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 650
    Points : 11 143
    Points
    11 143
    Par défaut
    Citation Envoyé par fjp Voir le message
    néanmoins je me pose la questions , pourquoi vouloir avoir une égalité dans ton programme , car même si tu cherches une occurrence dans un fichier son début sera le tellg ()
    Je ne cherche pas à avoir une égalité, je cherche à comprendre pourquoi tellg ne me retourne pas la position exacte de mon curseur.
    J'ai besoin de cette valeur pour connaître la position de certaines occurences dans le fichier. Si j'ai un décalage de 1, la valeur lue sera amputée de 1 caractère et ainsi ne correspondra plus à ce que je cherche.

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

Discussions similaires

  1. Fonction SQL IFNULL ne retourne pas la bonne valeur.
    Par Simka1000 dans le forum AS/400
    Réponses: 2
    Dernier message: 15/11/2013, 10h56
  2. getenv ne retourne pas la bonne valeur
    Par xaltar6 dans le forum Langage
    Réponses: 5
    Dernier message: 11/04/2013, 15h35
  3. Execute_query ne retourne pas les bonnes valeurs
    Par complicated dans le forum Forms
    Réponses: 2
    Dernier message: 23/11/2011, 11h12
  4. Méthode qui ne retourne pas la bonne valeur
    Par clubiste1920 dans le forum Débuter avec Java
    Réponses: 15
    Dernier message: 31/03/2011, 17h14
  5. [SQL Server] select max ne retourne pas la bonne valeur
    Par *alexandre* dans le forum Langage SQL
    Réponses: 7
    Dernier message: 29/09/2008, 14h49

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