Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 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 | | Calendrier |
|
|
| Remplacer un article dans un fichier texte | |
| | Auteur | Message |
---|
JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 21:48 | |
| Il s'agit de remplacer, dans un fichier texte, l'article d'un rang donné par un autre article (de longueur différente). La méthode qui vient à l'esprit est la suivante: - Lire successivement les articles et les recopier au fur et à mesure dans un fichier temporaire, en remplaçant au passage l'article désiré. - Recopier le fichier temporaire dans le fichier d'origine. - Supprimer le fichier temporaire. J'ai trouvé par hasard dans un autre forum une idée plus astucieuse, qui permet de se passer du fichier temporaire: - Code:
-
DIM f$, a$, b$, n, nr, art$, i LABEL Modif DATA "Pierre", "Paul", "Jacques", "Lucien", "Bertrand" DATA "Noël", "Julie", "Dominique", "Albert", "Jules" f$ = "Z:\Test.txt": ' ======== Fichier d'essai, à ajuster ! ============
' constitution du fichier test FILE_OPEN_WRITE 1, f$ FOR i = 1 TO 10: READ a$: FILE_WRITELN 1, a$: NEXT i FILE_CLOSE 1 nr = 4: art$ = "Népomucène": GOSUB Modif END
Modif: ' remplacer l'article de rang nr du fichier texte f$ par art$ FILE_OPEN_READ 1, f$: n = 0: a$ = "" WHILE FILE_EOF(1) <> 1 n = n + 1: FILE_READLN 1, b$ IF n = nr THEN b$ = art$ IF n > 1 THEN a$ = a$ + CHR$(13) + CHR$(10) a$ = a$ + b$ END_WHILE FILE_CLOSE 1 FILE_OPEN_WRITE 1, f$ FILE_WRITEBUF 1, a$, LEN(a$) FILE_CLOSE 1 RETURN | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 21:57 | |
| C'est intéressant, ma ça ne marche que pour les fichiers texte dont la longueur totale tient dans une variable string ! C'est en général le cas de fichiers de configurations, de listes simples etc. Mais ça ne marche pas pour de gros fichiers. Dans ce cas, il faut reprendre ton idée initiale, avec une légère modification: il s'agit bien de créer un fichier temporaire, puis lire le fichier en entrée et le recopier dans le fichier temporaire en remplaçant l'article visé au passage (qui pourrait être en paragraphe entier, par exemple...). Puis, on ferme les deux fichiers, on SUPPRIME le fichier en entrée et on RENOMME le fichier temporaire de sorte qu'il s'appelle comme le fichier en entrée. C'est bien sûr plus rapide que de le recopier et produit le même résultat. | |
| | | jjn4
Nombre de messages : 2747 Date d'inscription : 13/09/2009
| Sujet: +++ Dim 5 Sep 2010 - 22:47 | |
| @JL35 C'est une astuce intéressante. @klaus Mais la quelle est la longueur d'une variable string ? Ca doit cependant très grand ? | |
| | | JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Re: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 23:01 | |
| Ben oui ! je serais bien curieux de la connaître cette limitation des strings ? en général un fichier txt qu'on utilise n'est pas aussi gigantesque qu'un fichier image par exemple, et il me semblait qu'on pouvait difficilement atteindre la limite. Par exemple, en Qbasic, je lis(ais) sans problème un fichier binaire de 1 ou 2 mégas dans un seul string. Ca doit dépendre aussi de la mémoire installée, mais avec nos gigas actuels il ne doit pas y avoir de problème de ce côté-là. Alors où est la limite ? c'est une limite Panoramic ? Tiens je vais faire des essais avec de gros fichiers (enfin, leur copie, parce que ça les modifie... ou plutôt changer la fin pour réécrire dans un autre fichier) Je viens d'essayer avec un fichier texte de 1,2M, aucun problème, c'est assez long, il faut être patient, mais je ne suis pas sûr que ce serait plus rapide avec la méthode classique. En tout cas le string de 1,2M marche. @Klaus Je ne sais pas ce que tu appelles de gros fichiers, mais il est facile de chercher la limite et pas facile de la trouver. Si je fais: - Code:
-
DIM a$ a$ = STRING$(65000000, "S") PRINT LEN(a$) END ça marche très bien (il met un certain temps à constituer la chaîne, certes), mais pour moi on ne doit quasiment jamais rencontrer un fichier texte de 65M ou plus ! et ça marche encore ! Pour mon programme, j'avais dans l'esprit des fichiers de listes 'domestiques', noms, numéros de téléphone, que sais-je, mais pas les archives de la NSA. J'ai par exemple sur mon disque, par curiosité, la totalité de la bible sous la forme de 67 fichiers texte, dont un index, le total fait 4,3 M.
Dernière édition par JL35 le Dim 5 Sep 2010 - 23:44, édité 2 fois | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 23:32 | |
| La longueur d'un string étant codé sur 32 bits, la longueur maxi est donc de 2^^32-1 si c'est en représentation non signée, soit 4,294,967,295, ou 2^^31-1 si c'est en représentation signée, soit 2,147,483,647. Je ne sais pas quelle est la représentation interne - signée ou non signée, dans Panoramic.
Or, 4,294,967,295 représente 4 Go ce qui est énorme. Cela suffit bien sûr pour tous les fichiers texte, mais il ne faut pas oublier que le programme travaille en mémoire virtuelle. Même si on dispose d'une mémoire physique importante, disons 4 Go, la totalité n'est pas disponible pour notre string ! Il y a le système, tous les processus Windows et les autres, Panoramic, les DLL's (et il y en a beaucoup) etc. Tout ce petit monde se partage la mémoire virtuelle, et Windows se charge d'allouer de la memoire physique par morceaux plus ou moins grands, dynamiquement, suivant les besoins. La mémoire qllouée mais qui n'est pas immédiatement nécessaire pour le processus qui a la main, peut être "swappée" sur disque dans le fameux fichier de pagination. Et on en revientg aux lectures/écritures disque, car c'est bien de cela qu'il s'agit. Sans oublier que la demande démesurée de mémoire physique ralentit considérablement tout le fonctionnement du système qui passe son temps à gérer les conflits de mémoire.
Le problème est différent avec la partie "code" d'un programme qui en principe est "read-only" et qui génère moins de problèmes de conflit que la mémoire de "données" qui est dynamique. Pensez que chaque a$=a$+b$ crée momentanément le DOUBLE de l'espace mémoire nécessaire: au départ, il y a l'espace pour a$ plus l'espace pour b$, et l'opération "+" demande la création d'un espace de la longueur nécessaire pour l'opération en plus de l'existant, recopie tout dans le nouvel espace, puis libère l'espace de l'ancien a$, car l'opération "+" ne "rattache" pas b$ à la fin de a$, mais crée bien un espace temporaire de la longueur totale dans lequel l'opération de déroule, puis remplace la variable résultat par cet espace de travail. Cela fait des variations importantes de la mémoire occupée à chaque itération, et on recopie chaque fois tout depuis le début, ce qui donne forcément un ralentissement croissant au fil de l'avancement. Si les longueurs des 5 premières lignes sont 8,12,3,15,7, soit 10,14,5,17,9 avec le CR LF à ajouter (!), cela fait, au fil des itérations: 1. 10 octets 2. 10+14=24 octets avec un besoin temporaire de 48 octets 3. 24+5=29 octets avec un besoin temporaire de 58 octets 4. 29+17=46 octets avec un besoin temporaire de 92 octets 5. 46+9=55 octets avec un besoin temporaire de 110 octets etc. Il en resulte une fragmentation importante de la mémoire et une dégradation de performances réelle du système dans son ensemble, et cette dégradation peut persister même après l'arrêt du programme, du fait de la fragmentation de la mémoire. | |
| | | JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Re: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 23:42 | |
| J'éditais en même temps... j'entends bien tes arguments Klaus, et pour de gros fichiers il y aurait certes des inconvénients importants, mais il ne s'agit pas de programmes industriels, et on ne manipule en général que des fichiers texte de quelques dizaines, voire centaines de k.octets au grand maximum (je parle de fichiers de données personnelles), pour lesquels la méthode est utilisable (sans être obligatoire !). Bien sûr pour des applications plus professionnelles, il faudrait sans doute envisager autre chose, mais ce n'est pas ici notre domaine, il me semble.
Et puis c'était surtout histoire de communiquer une astuce qui m'a semblé originale et intéressante.
En tout cas merci pour tes arguments fort documentés sur l'utilisation de la mémoire par le système ! | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Remplacer un article dans un fichier texte Dim 5 Sep 2010 - 23:56 | |
| Je comprends... Pour de petits fichiers, ces considérations n'ont en effet pas d'incidence sensible. Au contraire, cela sera pus rapide en mémoire. Puis-je néanmoins de suggérer la petite modif de "beauté" suivante: - Code:
-
DIM f$, a$, b$, n, nr, art$, i DIM crlf$ LABEL Modif DATA "Pierre", "Paul", "Jacques", "Lucien", "Bertrand" DATA "Noël", "Julie", "Dominique", "Albert", "Jules" f$ = "Z:\Test.txt": ' ======== Fichier d'essai, à ajuster ! ============ crlf$ = ""
' constitution du fichier test FILE_OPEN_WRITE 1, f$ FOR i = 1 TO 10: READ a$: FILE_WRITELN 1, a$: NEXT i FILE_CLOSE 1 nr = 4: art$ = "Népomucène": GOSUB Modif END
Modif: ' remplacer l'article de rang nr du fichier texte f$ par art$ FILE_OPEN_READ 1, f$: n = 0: a$ = "" WHILE FILE_EOF(1) <> 1 n = n + 1: FILE_READLN 1, b$ IF n = nr THEN b$ = art$ ' IF n > 1 THEN a$ = a$ + CHR$(13) + CHR$(10) ' a$ = a$ + b$ IF n=2 THEN crlf$ = CHR$(13) + CHR$(10) a$ = a$ + crlf$ + b$ END_WHILE FILE_CLOSE 1 FILE_OPEN_WRITE 1, f$ FILE_WRITEBUF 1, a$, LEN(a$) FILE_CLOSE 1 RETURN cela évite de remplacer deux fois a$ dans la même itération.
Dernière édition par Klaus le Lun 6 Sep 2010 - 1:41, édité 1 fois | |
| | | JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Re: Remplacer un article dans un fichier texte Lun 6 Sep 2010 - 0:09 | |
| Mais tu peux Klaus ! effectivement je n'ai pas trop peaufiné le codage, c'était surtout pour le principe général, mais c'est plus joli comme ça. Quoique... tu remplaces 2 lignes par 2 autres lignes, avec le même test et une variable supplémentaire, pas sûr que ce soit plus optimisé... mais c'est un peu plus beau. Peut-être. Bonne nuit ! | |
| | | jjn4
Nombre de messages : 2747 Date d'inscription : 13/09/2009
| Sujet: +++ Lun 6 Sep 2010 - 1:01 | |
| @klaus Merci pour les explications @Tous Donc, la formule de JL35 est utilisable, puisque les fichiers aussi gros n'existent pas dans nos contrées. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Remplacer un article dans un fichier texte Lun 6 Sep 2010 - 1:44 | |
| J'ai corrigé une petite erreur dans le source de mon post. Bien sûr, je remplace 2 lignes par deux autres lignes. Mais j'ai corrigé la première: elle ne s'exécute plus qu'une selle fois. ET le but, c'est d'éviter de faire deux foia "a$=" dans une même itération pour des raisons que j'ai cité plus haut.
D'accord, avec de petits fichiers, cela n'a pas d'incidence visible. C'est un peu mon défaut: je regarde systématiquement le cas général... | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Remplacer un article dans un fichier texte Lun 6 Sep 2010 - 10:49 | |
| - Klaus a écrit:
- C'est un peu mon défaut: je regarde systématiquement le cas général...
A mes yeux ce serait plutôt une qualité : "penser globalement et agir localement" | |
| | | Jean Claude
Nombre de messages : 5950 Age : 70 Localisation : 83 Var Date d'inscription : 07/05/2009
| Sujet: Re: Remplacer un article dans un fichier texte Lun 6 Sep 2010 - 12:22 | |
| Comme je pigeais pas trop au départ l'intérêt du truc, je me suis permis d'ajouter un list pour visualiser le travail accompli par le code. Je trouve la combine intéressante... - Code:
-
DIM f$, a$, b$, n, nr, art$, i LABEL Modif
list 1: width 1,350:height 1,300:top 1,10:left 1,10
DATA "Pierre", "Paul", "Jacques", "Lucien", "Bertrand" DATA "Noël", "Julie", "Dominique", "Albert", "Jules" f$ = "C:\Test.txt": ' ======== Fichier d'essai, à ajuster ! ============
' constitution du fichier test FILE_OPEN_WRITE 1, f$ FOR i = 1 TO 10: READ a$: FILE_WRITELN 1, a$: NEXT i FILE_CLOSE 1 nr = 6: art$ = "LIGNE 6 Modifiée": GOSUB Modif: ' Variables à modifier
file_add 1,f$ END
Modif: ' remplacer l'article de rang nr du fichier texte f$ par art$ FILE_OPEN_READ 1, f$: n = 0: a$ = "" WHILE FILE_EOF(1) <> 1 n = n + 1: FILE_READLN 1, b$ IF n = nr THEN b$ = art$ IF n > 1 THEN a$ = a$ + CHR$(13) + CHR$(10) a$ = a$ + b$ END_WHILE FILE_CLOSE 1 FILE_OPEN_WRITE 1, f$ FILE_WRITEBUF 1, a$, LEN(a$) FILE_CLOSE 1 RETURN
A+ | |
| | | JL35
Nombre de messages : 7112 Localisation : 77 Date d'inscription : 29/11/2007
| Sujet: Re: Remplacer un article dans un fichier texte Lun 6 Sep 2010 - 14:15 | |
| @Jean-Claude, le seul intérêt, non négligeable, c'est d'éviter de créer un fichier temporaire. Le but n'était pas de gagner du temps (on n'est pas à quelques millisecondes près en plus ou en moins d'ailleurs).
@Klaus tu exécutes quand même le test if n=2 à chaque passage dans la boucle... il est sans doute possible d'optimiser si on envisage un usage intensif, mais je le répète, le but était de communiquer l'idée (qui je le répète n'est pas de moi, je l'ai trouvée dans un forum) avec un exemple rapide, si quelqu'un en a l'usage, tant mieux, et il pourra toujours l'adapter à son goût.
Cette histoire de FILE_READBUF permet finalement de lire la totalité du contenu d'un fichier dans un string, chose que je me plaignais de ne pas avoir. Quoique je craigne que ce soit un peu long, mais je vais bricoler un peu là-dessus. Décidément, une idée en entraîne une autre... ce n'est jamais fini ! PS: eh bien non, fausse joie ! on peut bien lire l'intégralité d'un fichier texte en une seule fois avec FILE_READBUF, mais s'il s'agit d'un fichier binaire, dès qu'un caractère '1A' est rencontré, celui-ci est répété jusqu'à la fin du fichier, alors que le string obtenu fait bien la bonne longueur, ce qui est très trompeur (et qui m'a bien trompé !). Je ne m'en souvenais plus mais je crois bien que j'avais déjà expérimenté ça. J'abandonne cette idée. Mais ça reste valable pour des recherches dans un fichier texte. | |
| | | Contenu sponsorisé
| Sujet: Re: Remplacer un article dans un fichier texte | |
| |
| | | | Remplacer un article dans un fichier texte | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |