Bonjour,
svp j'ai bien besoin de savoir si je peux accéder à un fichier.txt pour supprimer une partie? si oui, merci de bien vouloir m'aider![]()
Bonjour,
svp j'ai bien besoin de savoir si je peux accéder à un fichier.txt pour supprimer une partie? si oui, merci de bien vouloir m'aider![]()
Bonjour,
A priori ce n'est pas possible, il faut créer un fichier temporaire (ouvert en écriture) y mettre la partie de ton fichier d'origine (ouvert en lecture) que tu souhaites conserver puis effacer le fichier d'origine et renommer le fichier temporaire.
Pour la manipulation des fichiers :
http://melem.developpez.com/tutoriel...rs/?page=cours
Bonjour,
Comme l'a souligné pythéas, il faut créer un fichier temporaire.
J'ai trouvé ce code :
Source : cppfrance.
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
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 #include <stdio.h> #include <windows.h> // Taille du buffer de lecture #define ONEMEGA 0x100000 //Permet de supprimer la chaine String du fichier FileName DWORD deleteStringInFile(char *FileName, char *String); int main(int argc, char **argv) { // Test des paramètres if (argc != 3) { printf("Problem when calling the applicationn"); printf("Exemble: exe test.txt coucou2n"); system("pause"); return -1; } // Appel à la fonction DWORD result = deleteStringInFile(argv[1], argv[2]); printf("%sn", (result == 0) ? "pas trouvé" : "trouvé"); system("pause"); return 0; } DWORD deleteStringInFile(char *FileName, char *String) { char *buffer; // Buffer de lecture char *c, *pout; // Délimiteurs unsigned int i, lenfind = strlen(String); DWORD dwread, dwritten, bfound = 0; // Ouverture d'un fichier temporaire HANDLE htemp = CreateFile("temp.txt", GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_SEQUENTIAL_SCAN, 0); if (htemp == INVALID_HANDLE_VALUE) return 0; // Ouverture du fichier en mode lecture HANDLE hfile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); if (hfile == INVALID_HANDLE_VALUE) return 0; // Allocation du buffer dans le tas // sinon, stack overflow surement buffer = (char *) HeapAlloc(GetProcessHeap(), 0, ONEMEGA); fromFL: // Remplissage du buffer dwread = 0; ReadFile(hfile, buffer, ONEMEGA, &dwread, 0); if (bfound) { // Si la chaine a été trouvée, on se contente d'écrire // et on quitte si on a lu moins d'un Mo WriteFile(htemp, buffer, dwread, &dwritten, 0); if (dwread != ONEMEGA) goto closeFL; else goto fromFL; } // Si le nombre de caractères lus < taille de String alors exit if (dwread < lenfind) goto closeFL; // Init des délimiteurs pout = buffer + dwread - lenfind; c = buffer; firstcar: // test du 1er caractère while (*c != String[0]) { // Test s'il reste assez de caractères if (++c >= pout) { if (dwread != ONEMEGA) goto closeFL; WriteFile(htemp, buffer, dwread, &dwritten, 0); goto fromFL; } } for (i = 1; i < lenfind; i++) { if (c[i] != String[i]) goto notfound; } // OK! Chaine trouvée! bfound = 1; WriteFile(htemp, buffer, c - buffer, &dwritten, 0); WriteFile(htemp, c + lenfind, pout - c, &dwritten, 0); goto fromFL; notfound: // KO, pas trouvée :( // s'il reste assez de caractères, on continue avec le même buffer if (++c < pout) goto firstcar; if (dwread == ONEMEGA) { // sinon, lecture d'un nouveau buffer WriteFile(htemp, buffer, dwread, &dwritten, 0); goto fromFL; } closeFL: // Fermeture des fichiers CloseHandle(hfile); CloseHandle(htemp); // Si la chaine a été trouvée, on ré-écrit le fichier if (bfound) CopyFile("temp.txt", FileName, false); // Destruction du fichier temporaire DeleteFile("temp.txt"); // Désallocation du buffer HeapFree(GetProcessHeap(), 0, buffer); // Fin return bfound; }
Je n'ai pas testé, mais ça pourrait peut être t'aider.
Bonjour,
Envoyé par pythéas
Si le passage par un fichier temporaire est très souvent utilisé et convient généralement bien, il n'y a pas d'impossibilité technique à aller supprimer une partie d'un fichier (texte ou binaire) sans passer par un fichier temporaire.Envoyé par mirecalu
Attention, il n'y a pas de recette miracle : "aller supprimer une partie du fichier", c'est écrire, à la place de ce que l'on veut supprimer, ce qui vient après, c'est-à-dire "boucher les trous".
Je ne dis pas que cette technique est à utiliser à tout bout de champs mais, dans certains cas, elle peut être plus efficace que de réécrire quasiment tout le fichier, sauf quelques "trucs", dans un fichier temporaire (cas de très gros fichiers, avec des choses à enlever qui se situent "plutôt" vers la fin du fichier).
Il suffit pour ça :
- d'ouvrir le fichier en mode mise à jour "r+"
- de gérer deux positions courantes, une en lecture, une en écriture
- de bien se repositionner explicitement (via fseek) quand on passe d'une lecture à une écriture, ou l'inverse
- de tronquer (quand il s'agit d'une suppression, pas le choix) le fichier.
Mise en application sur un cas simple (qui ne justifie absolument pas d'utiliser cette méthode mais c'est pour l'exemple).
suppression des lignes de numéros pairs d'un fichier texte (ma première ligne a le numéro 1)
Appliqué au fichier source ci-dessus :
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 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define TAILLE_JAMAIS_ATTEINTE 128 int main(int argc,char *argv[]) { FILE *fp; char buffer[TAILLE_JAMAIS_ATTEINTE]; int noligne = 0; long position_lecture = 0L; long position_ecriture = 0L; fp = fopen(argv[1],"r+"); while(fgets(buffer,TAILLE_JAMAIS_ATTEINTE,fp)) { noligne += 1; // j'ai avance en lecture - je memorise la nouvelle position position_lecture = ftell(fp); if (noligne % 2) { // positionnement au bon endroit pour ecrire fseek(fp,position_ecriture,SEEK_SET); // ecriture fputs((const char *)buffer,fp); // memorisation de la position d'ecriture position_ecriture = ftell(fp); // repositionnement a la position de lecture pour le fgets qui suit fseek(fp,position_lecture,SEEK_SET); } } fclose(fp); // on tronque le fichier a sa "vraie" taille // Sous Windows, j'ai cru comprendre qu'on peut utiliser SetEndOfFile // sous Unix/Linux, on utilise truncate : truncate(argv[1],(off_t)position_ecriture); return 0; }
C'est sur que, maintenant, même s'il passait à la compilation, il marcherait beaucoup moins bien ...
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 plx@sony:~$ ./supprime_lignes_paires supprime_lignes_paires.c plx@sony:~$ plx@sony:~$ more supprime_lignes_paires.c #include <stdio.h> #include <unistd.h> #define TAILLE_JAMAIS_ATTEINTE 128 int main(int argc,char *argv[]) FILE *fp; int noligne = 0; long position_ecriture = 0L; fp = fopen(argv[1],"r+"); while(fgets(buffer,TAILLE_JAMAIS_ATTEINTE,fp)) noligne += 1; // j'ai avance en lecture - je memorise la nouvelle position { fseek(fp,position_ecriture,SEEK_SET); fputs((const char *)buffer,fp); position_ecriture = ftell(fp); fseek(fp,position_lecture,SEEK_SET); } fclose(fp); // on tronque le fichier a sa "vraie" taille // sous Unix/Linux, on utilise truncate : } plx@sony:~$
Mais cela demande d'utiliser des fonctions spécifiques au système (par exemple SetEndOfFile sous Windows). En d'autres termes, ce n'est pas portable. La seule façon portable d'arriver au résultat est d'utiliser un fichier temporaire.Envoyé par plxpy
Et j'ajoute qu'elle est toujours au moins aussi efficace que la façon fichier temporaire.Envoyé par plxpy
@mirecalu: C'est dommage d'utiliser des fonctions spécifiques à Windows pour implémenter un algorithme qu'on aurait pu écrire en C standard.
Partager