[DEBUTANT C] Modifier fichier texet [Résolu]

Signaler
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008
-
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
-
Bonjour

J'ai besoin, sur un vieux PC sous DOS, de modifier un fichier texte de la façon suivante :
Entre les 23ème et 24ème virgule, je dois ajouter le mot TEST, puis copier le fichier dans un répertoire K:\TEST

1-De quoi ai-je besoin pour que le programme tourne sous DOS ?
2-Comment faire ?

Je n'ai jamais fait de C, mais je connais VB par exemple

merci de votre patience...

Jean-Marc

14 réponses

Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Je viens de le tester sous Code::Blocks 8 (autre IDE C++ gratuit) et tout passe sans aucun problème.

Jean-François
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Voilà ! il suffit d'externaliser le traitement d'un fichier dans une fonction (TraiterFichier() ici) et d'appeler cette fonction dans une boucle de parcours des fichiers qui répondent aux critères :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>




// --- Constantes
static const int   iPositionInsertion = 24; // devant cette virgule
static const char* szInsertion = "TEST";
static const int   iLongueurInsertion = strlen(szInsertion);
static const char* szRepertoire = "K:\\TEST\";




 




// ------------------
// TRAITER UN FICHIER
// ------------------
bool TraiterFichier
(
   const char* pszNomFichierEntree // E:nom du fichier à traiter
)                                  // S:état du traitement
{
   // --- Buffer de lecture du fichier
   static const int iTailleBuffer = 64 * 1024; // taille maxi
   char acBuffer[iTailleBuffer];






   // --- Présentation du fichier à traiter
   printf("\nTraitement du fichier "%s"\n",pszNomFichierEntree);






   // --- Ouvrir/lire/fermer le fichier en entrée
   printf("- Lecture du fichier");
   FILE* fp = fopen(pszNomFichierEntree,"rt");
   if (fp == NULL)
   {
      printf(" *** ERREUR ***\n");
      return false;
   }
   int iTailleFichier = fread(acBuffer,1,iTailleBuffer,fp);
   fclose(fp);
   printf(", %d caracteres lus\n",iTailleFichier);






   // --- Traiter le buffer
   int iCompteurVirgule = 0;
   for (int i=0 ; i



            // --- 1) Décaler de "iLongueurInsertion" caractères
            for (int j=iTailleFichier ; j>=i ; --j)
               acBuffer[j + iLongueurInsertion] = acBuffer[j];



            // --- 2) Insérer le texte
            strncpy(&acBuffer[i],szInsertion,iLongueurInsertion);



            // --- 3) Traitement du buffer terminé
            iTailleFichier += iLongueurInsertion;
            break;
         }
      }
   }
   if (iCompteurVirgule < iPositionInsertion)
   {
      printf("- *** FICHIER NON MODIFIE ***\n");
      return true;
   }






   // --- Nom complet du fichier en sortie
   char szNomFichierSortie[_MAX_PATH];
   strcpy(szNomFichierSortie,szRepertoire);
   strcat(szNomFichierSortie,pszNomFichierEntree);






   // --- Ouvrir/écrire/fermer le fichier en sortie
   printf("- Ecriture du fichier "%s"",szNomFichierSortie);
   fp = fopen(szNomFichierSortie,"wt");
   if (fp == NULL)
   {
      printf(" *** ERREUR ***\n");
      return false;
   }
   fwrite(acBuffer,iTailleFichier,1,fp);
   fclose(fp);
   printf(", %d caracteres ecris\n",iTailleFichier);
   return true;
}




 




// -------------------
// FONCTION PRINCIPALE
// -------------------
int main(int argc,char** argv)
{
   // --- Nom du/des fichiers à traiter
   char szNomFichier[_MAX_PATH];






   // --- Présentation
   printf("\nMODIFICATION DE FICHIER(S)\n");
   if (argc == 1)
   {
      // --- Fichiers d'extension TXT par défaut
      strcpy(szNomFichier,"*.TXT");
   }
   if (argc == 2)
   {
      // --- Fichier(s) dans le paramètre 1
      strcpy(szNomFichier,argv[1]);
   }
   else if (argc > 2)
   {
      printf("Utilisation : test nom_fichier(s)\n");
      printf("Traiter le(s) fichier(s) "nom_fichier(s)" dans le repertoire courant\n");
      printf("Fichier(s) modifie(s) cree(s) dans le repertoire "%s"\n",szRepertoire);
      printf("Exemples de traitement :\n");
      printf("  test         --> tous les fichiers d'extension "txt"\n");
      printf("  test *.dat   --> tous les fichiers d'extension "dat"\n");
      printf("  test fic.*   --> tous les fichiers de nom "fic" quelque soit l'extension\n");
      printf("  test fic.log --> le fichier "fic.log"\n");
      return 0;
   }
   printf("Traitement de "%s"\n",szNomFichier);






   // --- Positionner sur le premier fichier du répertoire courant
   // --- et boucler tant qu'on trouve des fichiers
   WIN32_FIND_DATA Find;
   HANDLE hFichier = FindFirstFile(szNomFichier,&Find);
   do
      TraiterFichier(Find.cFileName);
   while (FindNextFile(hFichier,&Find));
   return 0;
}


Ce qui donne :

test



MODIFICATION DE FICHIER(S)
Traitement de "*.TXT"



Traitement du fichier "Test_modif_1.txt"
- Lecture du fichier, 106 caracteres lus
- Insertion de "TEST" devant la virgule 24
- Ecriture du fichier "Z:\Traces\Test_modif_1.txt", 110 caracteres ecri



Traitement du fichier "Test_modif_2.txt"
- Lecture du fichier, 71 caracteres lus
- Insertion de "TEST" devant la virgule 24
- Ecriture du fichier "Z:\Traces\Test_modif_2.txt", 75 caracteres ecris



Traitement du fichier "Test_modif_3.txt"
- Lecture du fichier, 83 caracteres lus
- Insertion de "TEST" devant la virgule 24
- Ecriture du fichier "Z:\Traces\Test_modif_3.txt", 87 caracteres ecris



Traitement du fichier "Test_modif_4.txt"
- Lecture du fichier, 71 caracteres lus
- Insertion de "TEST" devant la virgule 24
- Ecriture du fichier "Z:\Traces\Test_modif_4.txt", 75 caracteres ecris



Jean-François
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Et j'ai oublié le FindClose() !

   WIN32_FIND_DATA Find;
   HANDLE hFichier = FindFirstFile(szNomFichier,&Find);
   do
   {
      if ((Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
         TraiterFichier(Find.cFileName);
   } while (FindNextFile(hFichier,&Find));
   FindClose(hFichier);
   return 0;

Jean-François
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

Correction du titre
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Bonjour,

Voici un essai commenté en C/C++ (sous Visual C++ 6.0) qui peut être utilisé directement ou servir de base. Le fichier à modifier est passé en paramètre et doit se trouver dans le répertoire courant et ne pas faire plus de 64Koctets (modifiable dans le programme). Le fichier modifié est créé dans le répertoire K:\TEST avec le même nom :

#include <stdio.h>
int main(int argc,char** argv)
{
   // --- Constantes
   static const int   iPositionInsertion = 24; // devant cette virgule
   static const char* szInsertion = "TEST";
   static const int   iLongueurInsertion = strlen(szInsertion);
   static const char* szRepertoire = "K:\\TEST\";




   // --- Buffer de lecture du fichier
   static const int iTailleBuffer = 64 * 1024; // taille maxi
   char acBuffer[iTailleBuffer];






   // --- Présentation et contrôle du paramètre
   printf("\nMODIFICATION D'UN FICHIER\n");
   if (argc != 2)
   {
      printf("Utilisation: test nom_du_fichier\n");
      printf("Le fichier a modifier "nom_du_fichier" doit etre dans le repertoire courant\n");
      printf("Le fichier modifie "nom_du_fichier" est cree dans le repertoire "%s"\n",szRepertoire);
      return 0;
   }






   // --- Ouvrir/lire/fermer le fichier en entrée
   printf("Lecture du fichier %s\n",argv[1]);
   FILE* fp = fopen(argv[1],"rt");
   if (fp == NULL)
   {
      printf("*** Erreur a l'ouverture du fichier ***\n");
      return 0;
   }
   int iTailleFichier = fread(acBuffer,1,iTailleBuffer,fp);
   fclose(fp);
   printf("- %d caracteres lus dans %s\n",iTailleFichier,argv[1]);






   // --- Traiter le buffer
   int iCompteurVirgule = 0;
   for (int i=0 ; i




            // --- 1) Décaler de "iLongueurInsertion" caractères
            for (int j=iTailleFichier ; j>=i ; --j)
               acBuffer[j + iLongueurInsertion] = acBuffer[j];




            // --- 2) Insérer le texte
            strncpy(&acBuffer[i],szInsertion,iLongueurInsertion);




            // --- 3) Traitement du buffer terminé
            iTailleFichier += iLongueurInsertion;
            break;
         }
      }
   }
   if (iCompteurVirgule < iPositionInsertion)
   {
      printf("*** Fichier non modifie ***\n");
      return 0;
   }






   // --- Nom complet du fichier en sortie
   char szNomFichier[MAX_PATH];
   strcpy(szNomFichier,szRepertoire);
   strcat(szNomFichier,argv[1]);






   // --- Ouvrir/écrire/fermer le fichier en sortie
   printf("Ecriture du fichier %s\n",szNomFichier);
   fp = fopen(szNomFichier,"wt");
   if (fp == NULL)
   {
      printf("*** Erreur a l'ouverture du fichier ***\n");
      return 0;
   }
   fwrite(acBuffer,iTailleFichier,1,fp);
   fclose(fp);
   printf("- %d caracteres ecris dans %s\n",iTailleFichier,szNomFichier);
   return 0;
}


Ce qui donne :

C:\Temp\test test.txt

MODIFICATION D'UN FICHIER
Lecture du fichier test.txt
- 83 caracteres lus dans test.txt
Insertion de "TEST" devant la virgule 24
Ecriture du fichier K:\TEST\test.txt
- 87 caracteres ecris dans K:\TEST\test.txt

Fichier test.txt :
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,avant 23,,apres 24,0,1,2,3,4,5,6,7,8,9

Fichier K:\TEST\test.txt :
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,avant 23,TEST,apres 24,0,1,2,3,4,5,6,7,8,9

Jean-François
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

Merci beaucoup Jean-François

Par contre je ne possède par VC 6...  j'ai essayé de compiler avec BloodShield C++ (compilateur gratuit) mais j'ai plein d'erreur (notamment sur tout ce qui commence par str...), je suis en train de télécharger c++ 2008 express, mais cela sera-t-il compatible ?
De plus l'EXE généré passera-t-il sous DOS ?

Merci encore
Jean-Marc
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Il n'y a aucune raison que ça ne passe pas sous C++ express 2008, c'est du code très basique qui tourne sans problème sous DOS bien sûr. Il manque les 2 includes string.h et stdlib.h et il faut changer MAX_PATH en _MAX_PATH ! (le source dans lequel j'ai saisi cet exemple à d'autres includes que j'avais oublié de passer en commentaire)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char** argv)
{
   ...
   char szNomFichier[_MAX_PATH];
   ...
}

Jean-François
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

Génial, effectivement cela fonctionne, un très grand merci Jean-François, pour ta patience et tes explications.
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

J'ai peur d'abuser...mais je me lance !

Si je veux que cela fonctionne en lançant TEST.EXE *.TXT au lieu de donner le nom du fichier en paramètre c'est possible ? ou bien directement le fait de lancer TEST.EXE traite tous les fichiers en extension TXT ?

Merci d'avance aux âmes charitables qui ouvrent sur ce forum...

Jean-Marc
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

C'est tout à fait possible en utilisant les fonctions FindFirstFile() et FindNextFile().

Jean-François
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

Je viens d'aller à la pêche aux infos sur la fonction FindFirstFile et j'ai trouvé le code suivant. L'ennui c'est que mes connaissances en C sont trop limite pour savoir où brancher cette fonction...

HANDLE hFind;
WIN32_FIND_DATA FindData;

// Début de la recherche
hFind=FindFirstFile ("*.TXT", &FindData);
if (hFind!=INVALID_HANDLE_VALUE)
{
// Si le fichier trouvé n'est pas un dossier mais bien un fichier
if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
*** Faire le traitement ***
}
// Fichiers suivants
while (FindNextFile (hFind, &FindData))
{
if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
*** là j'ai pas compris à quoi cela correspond ****
}
}
}
// Fin de la recherche
FindClose (hFind);
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Ce code est "brut de décoffrage" bien sûr. Il manque quelques test de sécurité !
Par exemple, pour éliminer les répertoires qui pourraient être pris en compte :

   WIN32_FIND_DATA Find;
   HANDLE hFichier = FindFirstFile(szNomFichier,&Find);
   do
   {
      if ((Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
         TraiterFichier(Find.cFileName);
   } while (FindNextFile(hFichier,&Find));

Jean-François
Messages postés
7
Date d'inscription
mardi 22 avril 2008
Statut
Membre
Dernière intervention
22 avril 2008

Encore merci, problème solutionné, bravo l'artiste !

Jean-Marc
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009

Il vaut mieux prévoir les cas :
- aucun fichier à traiter
- ne pas modifier certains fichiers sensibles

   WIN32_FIND_DATA Find;
   HANDLE hFichier = FindFirstFile(szNomFichier,&Find);
   if (hFichier == INVALID_HANDLE_VALUE)
   {
      printf("*** AUCUN FICHIER A TRAITER ***\n");
   }
   else
   {
      do
      {
         // --- On ne traite ni les répertoires
         // --- ni certains fichiers spéciaux
         if
         (
            (Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0
            &&
            (Find.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) == 0
            &&
            (Find.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) == 0
            &&
            (Find.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) == 0
         )
         {
            TraiterFichier(Find.cFileName);
         }
      } while (FindNextFile(hFichier,&Find));
   }
   FindClose(hFichier);

Jean-François