Lire les lignes avec ReadFile

Résolu
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 - 25 août 2004 à 17:14
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 - 26 août 2004 à 11:59
Hello,

Je suis peut-être grave de chez grave, mais j'ai pas pigé comment lire une ligne précise d'un fichier avec ReadFile. Vu les commentaires sur le forum, c'est tellement basique que personne ne l'explique, mais moi je suis tout paumé du coup!

J'ai un fichier texte contenant 3 lignes. 2 lignes avec un chiffre de l'ordre de 2^512 et une avec un chiffre en binaire (80 bits).

Je veux les récupérer en char pour les traiter. Je suis sous VC6 dans win32, donc pas de fonction du type fgets...

Mais comme il paraît que ReadFile peut le faire, je n'ai qu'un mot à dire: HELP!

Thanx, Malik7934

13 réponses

malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
26 août 2004 à 11:59
J'en ai tellement roté pour trouver comment faire, que c'est avec plaisir que je poste cette réponse pour ceux qui auraient le même problème!!!!

Il s'agit d'une fonction qui permet de choisir la ligne qu'on veut lire. Tout est commenté... A+, malik7934

La fonction:
char* GetLineFromBuf(char* lpBuf, int iLine, int iNbLines) {
        // Vérifie les paramètres
        if(!lpBuf || (iLine < 0) || (iLine >= iNbLines))
                return NULL; // Mauvais paramètres

        while(iLine--)
                lpBuf += strlen(lpBuf) + 1;

        return lpBuf;
}

Le code:
        HANDLE hSrcFile   = INVALID_HANDLE_VALUE;
        char*  lpData     = NULL;
        char*  lpWork     = NULL;
        DWORD  dwFileSize = 0;
        int    nLines     = 0;
        DWORD  dwR;
        int    i;

        // Ouverrure du fichier
        hSrcFile = ::CreateFile("C:\\export.xml", GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

        // Vérifier l'ouverture
        if(hSrcFile == INVALID_HANDLE_VALUE) {
                // Erreur d'ouverture
                printf("Erreur d'ouverture du fichier!\n");

                // Sortir
                return 0;
        }

        // Récupérer la taille        if((dwFileSize ::GetFileSize(hSrcFile, NULL)) (DWORD)-1) {
                // Erreur de taille
                printf("Erreur sur la taille du fichier!\n");

                // Fermer le fichier
                ::CloseHandle(hSrcFile);
                hSrcFile = INVALID_HANDLE_VALUE;

                // Sortir
                return 0;
        }

        // Allouer un buffer (taille + 1 pour null char)        if((lpData (char*)malloc(dwFileSize + 1)) NULL) {
                // Erreur
                printf("Erreur d'allocation!\n");

                // Fermer le fichier
                ::CloseHandle(hSrcFile);
                hSrcFile = INVALID_HANDLE_VALUE;

                // Sortir
                return 0;
        }

        // Lire le fichier au complet
        if(!::ReadFile(hSrcFile, lpData, dwFileSize, &dwR, NULL)) {
                // Erreur de lecture
                printf("Erreur de lecture!\n");

                // Désalouer le buffer
                free(lpData);
                lpData = NULL;

                // Fermer le fichier
                ::CloseHandle(hSrcFile);
                hSrcFile = INVALID_HANDLE_VALUE;

                // Sortir
                return 0;
        }

        // Fermer le fichier
        ::CloseHandle(hSrcFile);
        hSrcFile = NULL;

        // S'assurer que le dernier byte est un null char
        *(lpData + dwFileSize) = '\0';

        // Convertir chaque retour de ligne en null char
        // Comme ça on a une suite de lignes dans le buffer
        // Attention: Il faut en même temps les compter pour
        // ne pas aller chercher une ligne inexistante par la suite

        // Du même coup, on supprime les \r qui peuvent être gênants
        lpWork = lpData;
        nLines = (*lpWork ? 1 : 0);
        while(*lpWork) {
                switch(*lpWork) {
                case '\r':
                        // Un caractère non voulu. On le supprime
                        memmove(lpWork, lpWork + 1, strlen(lpWork + 1) + 1);
                        // On reste à cette place
                        break;

                case '\n':
                        // Un retour de ligne. On le convertit en null char
                        *lpWork = '\0';
                        //On passe à la suite
                        lpWork++;
                        // Une nouvelle ligne
                        nLines++;
                        break;

                default:
                        // Un caractère, on le passe
                        lpWork++;
                        break;
                }
        }
        // Plus besoin de ça
        lpWork = NULL;

        // Maintenant on fait ce qu'on veut
        printf("Il y a %u lignes dans ce fichier. Les lignes sont :\n", nLines);
        for(i = 0; i < nLines; i++) {
                printf("Ligne %02u : %s\n", i + 1, GetLineFromBuf(lpData, i, nLines));
        }

        // Désalouer le buffer!
        free(lpData);
        lpData = NULL;
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 août 2004 à 17:27
Aspire dans un buffer avec ReadFile.
Pose un pointeur sur debut de buffer et avance le jusqu'au saut de ligne.

ciao...
BruNews, Admin CS, MVP VC++
0
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
25 août 2004 à 17:30
Hoi!

Ben en fait je viens de tomber sur une de tes sources ... EM_GETLINE!

Thanx, Malik7934
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 août 2004 à 17:42
C'est pour lire une ligne d'un EDIT, pas d'un fichier.

ciao...
BruNews, Admin CS, MVP VC++
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
25 août 2004 à 17:44
oops...

alors je retourne au turbin! Ceci dit, ça m'oblige à utiliser fgetc... et mon prog est pas copain avec ça (il a ses humeurs ;o))

Thanx, Malik7934
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 août 2004 à 17:52
Que vient faire fgetc dans cette galere ?
ReadFile ira beaucoup plus vite.

ciao...
BruNews, Admin CS, MVP VC++
0
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
25 août 2004 à 17:59
Alors je te dis: cf ma question du début!

A un moment, je lis un fichier que je stocke dans un buffer:

//Création du buffer pour lire le fichier source
dwFileSize = GetFileSize(hSrcFile,NULL) + 1;
szData = new char[dwFileSize];

//Lire le fichier source
if(!ReadFile(hSrcFile,szData,dwFileSize,&dwO,0))
{
delete[] szSrc;
delete[] szData;
CloseHandle(hSrcFile);
CloseHandle(hDestFile);
return FALSE;
}


char* szData est donc la copie du fichier lu (ou alors j'ai rien pigé). Maintenant je veux récupérer une à une les lignes... ben je pige pas.

Je voulais essayer un truc du genre
do{
c = fgetc(szData);
szSrc[x]=c;
x++;}
while ((c != '\n') && (c !='\r'))
Mais visiblement je suis trop une pine en C!
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 août 2004 à 18:25
char *c, *d, *pout;
DWORD d;

dwFileSize = GetFileSize(hSrcFile,NULL);
szData = new char[dwFileSize + 1];

d = 0; ReadFile(hSrcFile,szData,dwFileSize,&d,0);
CloseHandle(hSrcFile);
if(d != dwFileSize) ALORS MAUVAISE LECTURE, NETTOIE ET SORS.
d = szData;
pout = szData + dwFileSize;

BOUCLAGE:
c = d;
d avance jusque trouver saut ligne && < pout;
a ce moment c represente une ligne.
ON REBOUCLE.

ciao...
BruNews, Admin CS, MVP VC++
0
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
25 août 2004 à 18:29
Gros merci... je vais étudier ça de suite!

Malik7934
0
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
26 août 2004 à 09:04
Hi!

Sorry d'insister, mais je pige pas...

Bon, les déclarations d'usage:
char *c, *d, *pout;
DWORD dw;


On attrape la taille du fichier et on crée un nouveau char[] de la même taille:
dwFileSize = GetFileSize(hSrcFile,NULL);
szData = new char[dwFileSize + 1];


On initialise d à 0 et on met dans szData le fichier qu'on a lu, puis on referme le fichier qui vient d'être lu et qui nous sert plus:
d = 0; 
ReadFile(hSrcFile,szData,dwFileSize,&dw,0);
CloseHandle(hSrcFile);


Ensuite, on compare dw et dwFileSize.... Il n'y a pas de raison pour qu'ils soient identiques!!!:
if(dw != dwFileSize) ALORS MAUVAISE LECTURE, NETTOIE ET SORS.


Ensuite tu dis de mettre dans d ce qu'on a lu, puis d'initialiser pout à szData + dwFileSize... alors là, je pige pas. Char = Char + DWORD ? Ca sert à quoi?:
d = szData;
pout = szData + dwFileSize;
<table border=0 cellspacing=0 cellpadding=4 bgcolor=#E0E0E0>----,

Ensuite tu dis de faire une boucle comme suit (si j'ai bien compris):
<table border=0 cellspacing=0 cellpadding=4 bgcolor=#E0E0E0>----
<td class=code>
while ((d != "\n")&&(d

Ben avec ça, lorsque je regarde ce que j'ai dans c, j'ai que des symboles biscornus, pas la première ligne de mon fichier... j'suis à la rue là... %-6

help
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
26 août 2004 à 09:18
if(dw != dwFileSize) DOIVENT ETRE EGAUX en sortie sinon erreur de lecture du fichier. Regarde ReadFile dans MSDN et tu verras.

char = char + dword
NON PAS CHAR MAIS ADRESSE.
pout = szdata + dwFileSize; pout pointera alors sur l'octet qui suit le dernier du buffer lu par ReadFile.

Trop grosses lacunes en C, faut reviser et comprendre les pointeurs.

ciao...
BruNews, Admin CS, MVP VC++
0
malik7934 Messages postés 1154 Date d'inscription mardi 9 septembre 2003 Statut Membre Dernière intervention 15 août 2009 17
26 août 2004 à 09:36
100% d'accord sur les lacunes: mais j'ai pas le choix de faire du c. Sinon je poserais pas de questions et je serais en vacances! Pis plutôt que me balancer mes lacunes dans la tronche, un URL pour un tut genre "pointers for dummies" serait plus efficace ;o)

Donc... maintenant que j'entrevois la moindre le quoi-comment sur ces *ç%## de pointeurs, je repasse à l'attaque!

Je commente:

dwFileSize = GetFileSize(hSrcFile,NULL) + 1;
szData = new char[dwFileSize+1];

//Lire le fichier source
if(!ReadFile(hSrcFile,szData,dwFileSize,&dw,0))
{
delete[] szSrc;
delete[] szData;
CloseHandle(hSrcFile);
CloseHandle(hDestFile);
return FALSE;
}
CloseHandle(hSrcFile);


Jusque là, RAS.
Je mets d au même endroit que szData. pout, je le place à l'adresse correspondant à la fin de szData:

d = szData;
pout = szData + dwFileSize;


Tant que ce qui se trouve à l'adresse d n'est pas un symbole de retour à la ligne et tant que je ne suis pas à la fin de d, je fais le while suivant:

<td class=code>
while ((*d != '\n')&&(d

Ben pour un gros nul en c que je suis, je trouve ça pas mal... mais ça marche pas.

... BruNews, j'attends ton tut hein!
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
26 août 2004 à 09:43
Arrete de raler quand je parle lacunes, c'est pour ton bien que je signale ce qu'il convient de reviser.

*c = *d; ABSOLUMENT NON, il ne faut pas affecter les valeurs mais pousser 'd'.

while(*d != 10) { // cherche fin de ligne
if(++d >= pout) break; on touche la fin
}

etc....

ciao...
BruNews, Admin CS, MVP VC++
0
Rejoignez-nous