- Introduction à la méthode seek()
- Syntaxe de base
- Navigation depuis le début du fichier (whence=0)
- Navigation depuis la position actuelle (whence=1)
- Navigation depuis la fin du fichier (whence=2)
- Différence entre mode texte et mode binaire
- Cas pratique : Lecture d'un en-tête puis du corps
- Cas pratique : Modification ciblée dans un fichier
- Méthodes associées : tell() et truncate()
- Pièges courants et bonnes pratiques
- Exercice final : Lecture inversée
- Résumé des points clés
Ce tutoriel explique en détail l'utilisation de la méthode seek() pour naviguer dans un fichier, un concept fondamental pour la lecture et l'écriture non séquentielle.
1. Introduction à la méthode seek()
La méthode seek(offset, whence) permet de déplacer la position courante de lecture/écriture dans un fichier ouvert. Elle modifie le "pointeur de fichier".
- offset : Nombre de bytes à déplacer.
- whence (optionnel, défaut=0) : Point de référence pour le déplacement.
- 0 (os.SEEK_SET) : Début du fichier.
- 1 (os.SEEK_CUR) : Position actuelle.
- 2 (os.SEEK_END) : Fin du fichier.
2. Syntaxe de base
|
1 2 3 4 5 6 7 8 |
# Syntaxe générale fichier.seek(offset, whence) # Ou en important la constante du module os (plus lisible) import os fichier.seek(offset, os.SEEK_SET) # Début fichier.seek(offset, os.SEEK_CUR) # Position actuelle fichier.seek(offset, os.SEEK_END) # Fin |
3. Navigation depuis le début du fichier (whence=0)
Exemple de lecture à des positions spécifiques.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Création d'un fichier exemple with open('exemple.txt', 'w') as f: f.write("0123456789ABCDEFGHIJ") # 20 caractères # Lecture avec seek() with open('exemple.txt', 'r') as f: print(f"Position initiale : {f.tell()}") # 0 # Aller au 5ème byte (caractère '5') f.seek(5) print(f"Position après seek(5) : {f.tell()}") # 5 print(f"Lecture de 3 caractères : {f.read(3)}") # '567' # Retourner au début f.seek(0) print(f"Retour au début, position : {f.tell()}") # 0 print(f"Premier caractère : {f.read(1)}") # '0' # Aller au 10ème byte f.seek(10) print(f"Lecture depuis la position 10 : {f.read()}") # 'ABCDEFGHIJ' |
4. Navigation depuis la position actuelle (whence=1)
Déplacement relatif à la position courante du pointeur.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
with open('exemple.txt', 'rb') as f: # Mode binaire pour démonstration f.seek(5) # Aller à la position 5 print(f"Position : {f.tell()}") # 5 # Avancer de 3 bytes depuis la position actuelle f.seek(3, 1) # 1 = SEEK_CUR print(f"Position après seek(3, 1) : {f.tell()}") # 8 print(f"Lecture : {f.read(2)}") # b'89' ou '89' en texte # Reculer de 4 bytes depuis la position actuelle f.seek(-4, 1) # Offset négatif print(f"Position après seek(-4, 1) : {f.tell()}") # 6 print(f"Lecture : {f.read(2)}") # b'67' ou '67' |
5. Navigation depuis la fin du fichier (whence=2)
Utile pour lire des données à partir de la fin.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import os with open('exemple.txt', 'rb') as f: # Obtenir la taille du fichier f.seek(0, os.SEEK_END) taille = f.tell() print(f"Taille du fichier : {taille} bytes") # 20 # Lire les 5 derniers bytes f.seek(-5, os.SEEK_END) # Recule de 5 bytes depuis la fin print(f"Position : {f.tell()}") # 15 print(f"5 derniers caractères : {f.read()}") # b'FGHIJ' ou 'FGHIJ' # Positionnement impossible au-delà de la fin (en mode texte) f.seek(0, os.SEEK_SET) # Retour au début |
6. Différence entre mode texte et mode binaire
Attention : En mode texte ('r', 'w', 'a'), seek() est limité aux offsets retournés par tell() ou 0. Les offsets relatifs à la fin (SEEK_END) ne sont pas toujours autorisés.
|
1 2 3 4 5 6 7 8 9 10 |
# En mode texte (comportement restreint) with open('exemple.txt', 'r') as f: f.seek(10) # OK # f.seek(5, os.SEEK_END) # Possiblement erreur selon l'encodage print(f.read(5)) # En mode binaire (comportement complet) with open('exemple.txt', 'rb') as f: f.seek(-10, os.SEEK_END) # Toujours valide print(f.read()) |
7. Cas pratique : Lecture d'un en-tête puis du corps
Exemple réaliste de lecture d'un fichier avec une structure connue.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Simuler un fichier avec en-tête de 8 bytes et données data = b"HEADER__Donnees importantes du corps du fichier." with open('data.bin', 'wb') as f: f.write(data) # Lecture sélective with open('data.bin', 'rb') as f: # Lire l'en-tête (8 premiers bytes) header = f.read(8) print(f"En-tête : {header}") # b'HEADER__' # Se positionner après l'en-tête pour lire le reste # f.seek(8) # Équivalent f.seek(len(header)) # Plus dynamique corps = f.read() print(f"Corps : {corps.decode()}") # 'Donnees importantes...' |
8. Cas pratique : Modification ciblée dans un fichier
Remplacer un segment spécifique dans un fichier binaire.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Création d'un fichier binaire exemple contenu_original = b"XXXXX----REMPLACER----YYYYY" with open('modif.bin', 'wb') as f: f.write(contenu_original) # Remplacement du segment "REMPLACER" par "NOUVEAU___" with open('modif.bin', 'r+b') as f: # Mode lecture/écriture binaire # Trouver la position de début f.seek(5) print(f"À la position {f.tell()} : {f.read(11)}") # b'----REMPLACER' # Retourner à la position de remplacement f.seek(9) # Après "----" f.write(b"NOUVEAU___") # Doit être exactement 10 bytes comme "REMPLACER" # Vérification with open('modif.bin', 'rb') as f: print(f"Résultat : {f.read()}") # b'XXXXX----NOUVEAU___----YYYYY' |
9. Méthodes associées : tell() et truncate()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
with open('exemple_assoc.txt', 'w+') as f: # Lecture/écriture f.write("Hello World!") # tell() retourne la position actuelle pos = f.tell() print(f"Position après écriture : {pos}") # 12 # seek() + truncate() pour réduire la taille f.seek(5) f.truncate() # Tronque le fichier à la position actuelle (5) f.seek(0) print(f"Contenu tronqué : {f.read()}") # 'Hello' # truncate() avec une taille explicite f.seek(0) f.truncate(10) # Fichier étendu ou réduit à 10 bytes f.write("1234567890") f.seek(0) print(f"Contenu final : {f.read()}") # '1234567890' |
10. Pièges courants et bonnes pratiques
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 1. Ne pas dépasser les limites with open('test.txt', 'w') as f: f.write("abc") with open('test.txt', 'r+') as f: try: f.seek(10) # Position au-delà de la fin f.write("X") # Comportement différent selon le mode except Exception as e: print(f"Erreur possible : {type(e).__name__}") # 2. Gérer les encodages en mode texte with open('test_utf8.txt', 'w', encoding='utf-8') as f: f.write("éèà") # Caractères multi-bytes with open('test_utf8.txt', 'rb') as f: # Mieux en binaire pour seek() f.seek(1) # On se place au milieu d'un caractère UTF-8 print(f.read(2)) # On obtient des bytes partiels # 3. Toujours vérifier la position avec tell() with open('exemple.txt', 'r') as f: f.read(5) print(f"Position avant seek : {f.tell()}") f.seek(0) print(f"Position après seek(0) : {f.tell()}") |
11. Exercice final : Lecture inversée
Lire un fichier à l'envers en utilisant seek().
|
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 |
def lire_a_l_envers(nom_fichier): """Affiche le contenu d'un fichier à l'envers ligne par ligne.""" with open(nom_fichier, 'rb') as f: # Aller à la fin f.seek(0, os.SEEK_END) position = f.tell() ligne = b'' while position > 0: position -= 1 f.seek(position) caractere = f.read(1) if caractere == b'\n': # Ligne complète trouvée print(ligne.decode()[::-1]) # Inverser la ligne ligne = b'' else: ligne = caractere + ligne # Dernière ligne (première du fichier) if ligne: print(ligne.decode()[::-1]) # Création d'un fichier test with open('inverse.txt', 'w') as f: f.write("Première ligne\nDeuxième ligne\nTroisième ligne\n") print("Lecture à l'envers :") lire_a_l_envers('inverse.txt') # Affichera : # Troisième ligne # Deuxième ligne # Première ligne |
12. Résumé des points clés
- seek() contrôle la position du pointeur dans le fichier.
- En mode binaire ('rb', 'wb+', etc.), tous les déplacements sont autorisés.
- En mode texte, les offsets doivent être des valeurs retournées par tell() ou 0.
- whence détermine le point de référence (début, position actuelle, fin).
- Toujours utiliser tell() pour déboguer la position.
- Pour des manipulations complexes, privilégier le mode binaire.
Younes Derfoufi
CRMEF OUJDA



