Bonjour,
J'avais une question à vous poser concernant la lecture d'un fichier: est ce possible d'accéder à la ligne 16 par exemple d'un fichier sans que je lise les 15 premières lignes?
Merci...
Version imprimable
Bonjour,
J'avais une question à vous poser concernant la lecture d'un fichier: est ce possible d'accéder à la ligne 16 par exemple d'un fichier sans que je lise les 15 premières lignes?
Merci...
Question récurrente, c'est impossible.
Pour compléter la réponse de Melem, on peut s'en sortir à coup de fseek() si les lignes ont une taille fixe ou en gérant à la main un index de ligne.
Mais c'est assez complexe pour un gain qui est, sauf cas particulier, plutôt faible si ce n'est nul.
Que les lignes aient une taille fixe ne change rien. La doc de int fseek(FILE *stream, long int offset, int whence) dit bien :Citation:
Envoyé par gl
Citation:
For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_SET.
Mais pour créer la table des index il faut avoir déjà lu toutes les lignes.Citation:
Envoyé par gl
Oups ! Effectivement j'ai oublié de mettre en avant les habituelles restrictions de cette méthode.
Le fonctionnement n'est en effet pas garantie par le standard et n'est donc pas 100% portable. Bien qu'en pratique cela fonctionne plutôt bien sur les plate-formes que je connais (mais le code n'est pas portable).
Il est également possible de le faire lors de l'écriture du fichier. Mais surtout cela peut être fait une fois pour toute lors de la première lecture si le fichier est souvent lu mais jamais modifié.
Dans tous les cas ce n'est utilisable qu'en interne (i.e. pas question de transférer le fichier texte et l'index dans une autre environnement en espérant que ça marche).
Ceci étant, sauf cas particuliers, c'est assez inutile comme pratique.
bah..
La seule non-portabilité est le `\n' par rapport au '\n\r"...
Donc je trouve que la norme "abuse"...
Déjà c'est quasi inexistant des systèmes qui utilisent \n\r comme marqueur de fin de ligne. Tu voulais sûrement parler de la séquence \r\n, utilisée sous DOS et Windows entre autres, mais c'est vrai que cela ne change pas grand-chose à ce que tu as dit.
Maintenant en parlant d'abus.
La philosophie du mode texte c'est que certaines séquences d'octets peuvent avoir une signification spéciale. La marque de fin de ligne est un exemple bien connu mais il y en a d'autres, pour ne citer que le caractère de code 26 (Ctrl + Z) qui est interprété comme le marqueur de fin de fichier texte sous Windows par exemple (mais un fichier texte peut ne pas comporter ce caractère). Donc si tu utilises fseek sur un fichier texte ouvert en lecture et contenant le caractère Ctrl + Z (suppose par exemple que ce caractère apparaisse en plein milieu du fichier), tu pourrais ne pas avoir les mêmes résultats sous Windows puis sous Linux par exemple. => Ton programme n'est pas portable.
Même au sein d'un et un seul système (prenons Windows par exemple) l'effet d'un fseek avec des valeurs autres que 0 ou une valeur retournée par ftell pour offset et SEEK_SET pour whence sur un fichier texte n'est pas toujours évident. Si ton fichier est encodé en UTF-8 par exemple et que tu l'ouvres en mode texte UTF-8. Selon toi, un fseek sur ce fichier devrait te positionner à l'octet d'index offset ou au caractère d'index offset ? Même MSDN ne répond pas à cela :
C'est la même spécification que celle dans la norme du C. Il ne faut pas chercher à compliquer.Citation:
The only fseek operations guaranteed to work on streams opened in text mode are:
* Seeking with an offset of 0 relative to any of the origin values.
* Seeking from the beginning of the file with an offset value returned from a call to ftell.
Euh....
Quand on fait fopen ( fichier, "r")
puis qu'on fait fseek, en quoi est-ce qu'on se réfère à UTF8 ou à CTRL-Z ??
Si on fait un getc, ou fgets, le fait de tomber sur CTRL-Z (ou par exemple CTRL-M si on lit un fichier Win sous Unix) n'empêche en rien la lecture...
C'est là que je comprend pas...
Que l'interpétation des séquences soient faussée, je veux bien... Mais ça c'est au lecteur de le savoir..
Mais la lecture du fichier du début jusqu'à EOF, ou le déplacement d'un certain nombre d'octets m'apparaît comme totalement indépendant...
Ou alors je manque quelque chose...
PS: et là je ne parle pas de philosophie d'un fichier texte, mais de ce que dit la norme à propos de fseek ... qui normalement est un déplacement en octets.. ou tout au moins en unités du filesystem..
Il existe des extensions non standard (je l'ai bien précisé dans mon précédent message) aussi bien sous Windows que sous d'autres systèmes qui permettent d'indiquer le codage utilisé par le fichier texte. Dans UTF-8 les codes n'ayant pas tous la même longueur en bits, un getc peut te retourner un caractère 8 bits alors qu'il a pu faire avancer le caractère de 16 et non de 8 bits par exemple.Citation:
Quand on fait fopen ( fichier, "r")
puis qu'on fait fseek, en quoi est-ce qu'on se réfère à UTF8
Alors je continue :Citation:
ou à CTRL-Z ??
Citation:
Also in text mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing, fopen and all related routines check for a CTRL+Z at the end of the file and remove it if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z may cause fseek to behave improperly near the end of the file.
ok. Mais ça ça a à voir aec le filesystem.. Tu auras la même chose avec stat ou autres..
Mais pour la 2ième partie :
DONC une fois le fichier ouvert avec fopen, on devrait pouvoir utiliser fseek :DCitation:
Also in text mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing, fopen and all related routines check for a CTRL+Z at the end of the file and remove it if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z may cause fseek to behave improperly near the end of the file.
Maintenant, ça c'est pour rw.. Pour r seulement, je ne vois pas trop..
Non : DONC une fois le fichier ouvert avec fopen en mode lecture ET écriture, comme tu l'as précisé plus bas, le Ctrl + Z est supprimé s'il est présent, et s'il peut être supprimé. Ensuite, on peut évidemment utiliser fseek comme on le peut sur n'importe quel fichier texte, contenant un Ctrl + Z ou pas, MAIS en respectant les restrictions concernant cette utilisation de fseek sur un fichier texte. Ces restrictions rendent impossible d'aller à une ligne n d'un fichier texte sans avoir déjà passé au moins une fois par toutes les lignes précédentes, pour en revenir au sujet.Citation:
DONC une fois le fichier ouvert avec fopen, on devrait pouvoir utiliser fseek :D
Pour r seulement bin tu fais fgetc par exemple et que le caractère lu est Ctrl + Z, fgetc retournera EOF, pas Ctrl + Z.Citation:
Maintenant, ça c'est pour rw.. Pour r seulement, je ne vois pas trop..
Pour arriver à la ligne N oui..
Mais ce que je veux dire, c'est quand dans le genre de cas comme exposé par un posteur ailleurs, tu peux faire de la dichotomie et arriver à la ligne voulue sans être passé par toutes les lignes précédentes.. (par exemple si tu cherches une date dans un fichier où chaque ligne commence par une date)
C'est pour cela que je trouve que la norme "abuse"...
Tu fais apparemment référence à cette discussion.
Je répète que c'est impossible en C standard. Dans la discussion que tu cites, le fichier est ouvert en mode binaire, c'est pourquoi on peut faire des fseek pour aller n'importe où sans être déjà passé par tous les caractères précédents. En tout cas le programme au centre de cette discussion n'est elle non plus pas portable ...Citation:
tu peux (...) arriver à la ligne voulue sans être passé par toutes les lignes précédentes