IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Copier / Coller d'un fichier txt


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut Copier / Coller d'un fichier txt
    Bonjour,

    Le but de ce petit script est de mettre à jour des fichiers de configuration utilisé par une application.
    J'ai donc un dossier qui contient mes fichiers de configuration : C\MonAppli\cfg qui contient cfgserver.txt, cfgoracle.txt, cfgappli.txt...
    Et un dossier qui contient une ou plusieurs lignes à rajouter sur un ou plusieurs fichiers de configuration : C:\MAJ\cfgserver.txt, cfgappli.txt.
    Dans cet exemple je dois récupérer le contenu de cfgserver.txt et le mettre à la fin du fichier C:\MonAppli\cfg\cfgserver.txt idem avec cfgappli.txt.
    Ce n'est pas tout le temps les mêmes fichiers à mettre a jour. Parfois j'en ai qu'un.

    Passons à la structure des fichiers :
    Dans C:\MonAppli\cfg\ les fichiers sont structurés ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    {
    {Le contenu du fichiers}
    {encore un}
    }
    Le fichier commence par un { et fini par } il faut donc insérer le texte avant ce caractère; A noter que ce caractère est utilisé plusierus fois dans le fichier.

    Dans le dossier C:\MAJ
    Les fichiers ne sont pas strucuré. Il faut donc récupérer le contenu tel quel et le coller avant la fin du } de l'autre fichiers

    J'espère avoir été clair.

    D'avance merci pour vos réponses.

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Ce que j'ai compris, c'est qu'il faut ajouter un insert JUSTE AVANT la DERNIÉRE parenthèse '}'.
    La fonction rfind() va nous servir à trouver la position de cette dernière parenthèse dans la succession de caractères qu'est le fichier.

    Il faut insérer du texte avant cette dernière parenthèse. Ça c'est la représentation intellectuelle de ce qu'on veut faire.

    En pratique, on ne peut pas écarter des octets sur un disque dur pour mettre des octets supplémentaires entre eux dans un fichier.

    On peut seulement, en mode 'r+' :
    - positionner le pointeur du fichier à la position p à partir de laquelle on veut ajouter l'insert dans le fichier
    - enregistrer tous les caractères qui suivent cette position, jusqu'à la fin du fichier = chaine postp
    - ramener le pointeur à la position p, car le fait de lire l'a emmené à la fin du fichier
    - écrire l'insert dans le fichier à partir de la position p, c'est à dire que les caractères préexistant situés après p sont ÉCRASÉS (c'est le mode 'r+')
    - une fois finie cette écriture-écrasement, le pointeur peut être en plein milieu des caractères qui constituaient la fin du fichier après p (chaine postp), ou en zone vierge après ces caractères (qui ont été écrasés) après débordement de la fin du fichier. Je le dis pour que ce soit bien clair, mais ça n'a aucune importance pratique
    - le pointeur étant à la fin de l'insert, il suffit alors de poursuivre l'écriture en réécrivant la chaine postp qui se retrouve ainsi in fine déplacée sur le disque dur

    Voilà comment je comprends les choses, merci de me dire si je me trompe sur un point ou un autre.



    Dans le cas que tu nous soumets, brandtance, '{' est le seul caractère qu'il faut réécrire après l'insert. On ne va donc pas faire son enregistrement préalable dans postp, on sait que c'est lui qui est à ajouter comme chaine postp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fi = open('C:\MAJ\cfgserver.txt')
    insert = fi.read()
    fi.close()
     
    g = open('C:\MonAppli\cfg\cfgserver.txt','r+')
    ch = g.read()
    p = ch.rfind('{')
    g.seek(p)
    g.write(insert + '{')
    g.close()

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Salut et merci pour cette belle réponse.

    Citation Envoyé par eyquem Voir le message
    Ce que j'ai compris, c'est qu'il faut ajouter un insert JUSTE AVANT la DERNIÉRE parenthèse '}'.
    Oui c'est ça
    La fonction rfind() va nous servir à trouver la position de cette dernière parenthèse dans la succession de caractères qu'est le fichier.
    Jusque là je suis ;-)
    Il faut insérer du texte avant cette dernière parenthèse. Ça c'est la représentation intellectuelle de ce qu'on veut faire.
    Ok, c'est exact.
    On peut seulement, en mode 'r+' :
    - enregistrer tous les caractères qui suivent cette position, jusqu'à la fin du fichier = chaine postp
    J'avoue que la je suis un peu perdu : car si tu cherches '}' c'est la fin du fichier, donc tu n'a plus besoin d'enregistrer les caractères suivant...
    - ramener le pointeur à la position p, car le fait de lire l'a emmené à la fin du fichier
    - écrire l'insert dans le fichier à partir de la position p, c'est à dire que les caractères préexistant situés après p sont ÉCRASÉS (c'est le mode 'r+')
    - une fois finie cette écriture-écrasement, le pointeur peut être en plein milieu des caractères qui constituaient la fin du fichier après p (chaine postp), ou en zone vierge après ces caractères (qui ont été écrasés) après débordement de la fin du fichier. Je le dis pour que ce soit bien clair, mais ça n'a aucune importance pratique
    - le pointeur étant à la fin de l'insert, il suffit alors de poursuivre l'écriture en réécrivant la chaine postp qui se retrouve ainsi in fine déplacée sur le disque dur
    Je suis pas sûr d'avoir compris (désolé je suis en mode boulet) : en fait tu mets en buffer le contenu du fichier puis tu effaces le contenu ensuite tu colles le nouveau contenu du fichier qui est accompagné du nouveau fichier c'est ça ?

    Voilà comment je comprends les choses, merci de me dire si je me trompe sur un point ou un autre.


    Dans le cas que tu nous soumets, brandtance, '{' est le seul caractère qu'il faut réécrire après l'insert.
    Euh, non, j'ai dis ça moi ? lol

    En tout cas merci pour tout! Je vais tester ton code!!!

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Arf, le code ne marche pas tout a fait comme je voudrais :
    Voici mon fichier qui se trouve dans le dossier MAJ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ici je mets le contenu de mon fichier ligne 1
    ici je mets le contenu de mon fichier ligne 2
    ici je mets le contenu de mon fichier ligne 3
    ici je mets le contenu de mon fichier ligne 4
    Voici le contenu du fichier à mettre à jour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    {
    Ligne 1 de mon fichier de configuration
    Ligne 2 de mon fichier de configuration {Ici je test les caracteres}
    Ligne 3 de mon fichier de configuration
    }
    Il faudrait donc insérer le texte avant le dernier '}'

    Mais voici le résultat lorsque j'execute ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    {
    Ligne 1 de mon fichier de configuration
    Ligne 2 de mon fichier de configuratioici je mets le contenu de mon fichier ligne 1
    ici je mets le contenu de mon fichier ligne 2
    ici je mets le contenu de mon fichier ligne 3
    ici je mets le contenu de mon fichier ligne 4
    {
    Voici mes remarques :
    - Il faudrait que la première ligne inserer soit sur une nouvelle ligne, et non en continu (Ligne 2 de mon fichier de configuratioici je mets le contenu de mon fichier ligne 1)
    - Si il y a d'autres caractères {} ils sont supprimés
    - Le dernier caractère du fichier doit être un } et non un {


    J'essaie de modifier le code mais je galère
    En tout cas merci.

  5. #5
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Si ce fichier de configuration ne doit être lu que par des scripts python, ce serait certainement plus simple de sérialiser ces données avec pickle ou shelve.

    Ces deux modules te permettent de stocker telles qu'elles des structure de données python, sans t'ennuyer avec tout ce bazar qu'est la gestion d'un fichier texte et la création d'une structure flexible.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Malheureusement ta solution n'est pas possible. Je t'explique c'est pour la mise à jour d'une application et ces fichiers sont parfois modifié à la main (via un éditeur de texte).
    J'ai besoin d'un script pour 'industrialisé' la mise à jour de l'application qui est utilisé dans plusieurs établissements. En gros pour mettre à jour mon application je voudrais juste lancer ce script au lieu d'éditer x fichiers sur y établissements. Cependant, comme dit plus haut, la modification se fait parfois à la mano pour changer des options.

    Merci,

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    J'ai avancé un peu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    fi = open('C:\MAJ\cfgserver.txt')
    insert = fi.read()
    fi.close()
     
    g = open('C:\MonAppli\cfg\cfgserver.txt','r+')
    ch = g.read()
    p = ch.rfind('}')
    g.seek(p)
    g.write("\n"+insert + '}')
    g.close()
    Le seul problème maintenant c'est qu'il me supprime le dernier caractère de mon fichier C:\MonAppli\cfg\cfgserver.txt

  8. #8
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    On peut seulement, en mode 'r+' :
    - positionner le pointeur du fichier à la position p à partir de laquelle on veut ajouter l'insert dans le fichier
    - enregistrer tous les caractères qui suivent cette position, jusqu'à la fin du fichier = chaine postp
    - ramener le pointeur à la position p, car le fait de lire l'a emmené à la fin du fichier
    - écrire l'insert dans le fichier à partir de la position p, c'est à dire que les caractères préexistant situés après p sont ÉCRASÉS (c'est le mode 'r+')
    - une fois finie cette écriture-écrasement, le pointeur peut être en plein milieu des caractères qui constituaient la fin du fichier après p (chaine postp), ou en zone vierge après ces caractères (qui ont été écrasés) après débordement de la fin du fichier. Je le dis pour que ce soit bien clair, mais ça n'a aucune importance pratique
    - le pointeur étant à la fin de l'insert, il suffit alors de poursuivre l'écriture en réécrivant la chaine postp qui se retrouve ainsi in fine déplacée sur le disque dur
    Ceci est la description générale de la procédure d' "insertion" dans un fichier, pas la description de ce qu'il faut faire dans le cas particuliers de tes fichiers.

    Si on veut faire une "insertion" dans un texte de 2000 caractères à la position 800, on ne va pas écrire à la main dans le code 1200 caractères si on les connait à l'avance;
    même si on est dans ce cas où on connait a priori les 1200 caractères qui seront à réécrire, on est bien obligé de les capter dans le fichier, les enregistrer dans une variable et les réécrire de façon décalée une fois qu'aura été écrasé avec l'insert le début de leur succession.


    ----


    Pour ce qui est de ton cas particulier, j'ai bien vu que '}' est le dernier caractère et qu'il n'est pas nécessaire de faire la partie 'enregistrement de postp' pour mettre en réserve ce seul caractère. C'est pourquoi je voulais écrire:

    Dans ton cas, '}' est le seul caractère qu'il faut réécrire après l'insert. On ne va donc pas faire son enregistrement préalable dans postp, on sait que c'est lui qui est à ajouter comme chaine postp:
    Malheureusement, comme une andouille, je me suis trompé !! , j'ai écrit '{' à la place de '}' ,c'est une erreur ! Désolé pour la confusion que ça induit.


    ----------------------------------------------------------------------------------------


    «en fait tu mets en buffer le contenu du fichier puis tu effaces le contenu ensuite tu colles le nouveau contenu du fichier qui est accompagné du nouveau fichier c'est ça ?»
    Non, ce n'est pas tout à fait ça.
    Je ne sais pas si c'est en buffer ou pas en buffer.
    En tous cas oui, il faut enregistrer postp dans une variable;
    Et non, postp n'est pas le contenu du fichier, c'est seulement la portion de fichier qui se trouve après la position p à laquelle on veut faire l' "insertion".

    Mais je m'aperçois que le principe général n'est en lui-même pas immédiatement clair et que mes explications sont obscurcies par le fait que j'ai décrit la procédure générale mais que le code que j'ai écrit ne concerne que ton cas particulier. Je n'aurais pas dû mélanger les deux.
    Par dessus le marché, je me suis aperçu en creusant le sujet aujourd'hui que l'existence de divers types de fichiers complique les choses.


    -----------------

    Pour ce qui est de la procédure en général:



    En fait, si on veut intervenir sur des fichiers au moyen de programmes, il faut avoir les idées un peu clarifiées sur quelques points de base. J'écris 'clarifiées' et non pas 'claires' parce que je ne prétends pas être un expert des fichiers, il vaut mieux ne pas l'oublier.



    Le préalable, c'est qu'il ne faut pas en rester à une représentation intellectuelle d'un fichier sous une forme influencée par l'aspect visuel que présente ce fichier à l'écran quand on l'affiche (ça a été mon cas un certain temps, et je n'y comprenais rien)
    intellectuellement, cette représentation d'un fichier comporte des lignes, des différences de police, des différences de grosseur de caractères, de la couleur...
    Cette représentation intellectuelle est une chose mais la nature concrète d'un fichier sur un disque dur en est une autre et ce n'est pas la représentation intellectuelle qui permet de faire des programmes, c'est une compréhension minimum de la nature physique des fichiers qui importe pour pouvoir se débrouiller avec les fichiers.

    Or cette nature est simple, ce n'est rien d'autre qu'une succession de caractères, inscrits les uns après les autres dans un "sillon" unidimensionnel sur le disque dur, et même, pour être plus exact, puisque les caractères sont représentés par des octets composés eux mêmes de bits, un fichier physique n'est rien d'autre qu'une succession de bits: l'ordinateur ne voit que des bits qui se succèdent sans autre distinction que leur valeur 0 ou 1.

    Cependant parmi les caractères du source d'un fichier, il y en a qui apparaissent à l'écran quand on affiche le fichier (ils constituent le texte), et il y en a d'autres qui n'apparaissent pas à l'affichage parce qu'ils forment des groupes de caractères ayant chacun une signification particulière pour l'interpréteur qui affiche le fichier. Ces groupes spéciaux, qu'on peut appeler je pense des balises, même quand il s'agit d'un fichier Word ou de je ne sais quel autre type de fichier différent du HTML ou du XML, assurent le codage des caractéristiques évoquées plus haut: police de caractère, taille, retours à la ligne, tabulations,etc.

    Tous les types de fichiers n'assurent pas la prise en compte et le codage de ces différentes caractéristiques de la même manière.
    Dans tous les types, y compris le type minimal Texte Brut on trouve au minimum le retour à la ligne (il est codé par '\n') et la tabulation '\t'.
    Dans un texte de type plus sophistiqué, par exemple .txt, il y a d'autre balises qui ne seront pas interprétées comme balises par l'interpréteur de Texte Brut:
    ainsi '\\b ' devant et '\\b0 ' après un mot dans un fichier .txt le fera apparaître en gras si on lit le fichier avec un interpréteur de fichier .txt. Mais avec un WordPad, on verra affichés '\b ' et '\b0 '.

    En fait, à ce niveau là, c'est assez touffu et il faut regarder très précisément les choses, je ne connais pas tous ces détails de mémoire, je me trompe peut ètre sur un point ou un autre, mais l'idée importante est là:
    il n'y a rien de physiquement spécial qui constitue un retour à la ligne ou une autre balise, dans un fichier physique; les balises sont spécifiées par certains groupes de caractères conventionnels, qui, lorsqu'ils sont INTERPRÉTÉS par l'affichage du fichier, provoquent un effet donné.

    Et donc, un fichier, physiquement, est un suite de caractères. Il faut savoir lesquels.


    Et maintenant, voici une astuce considérable, que j'ai mis 1an et demi à trouver.
    Comment visualiser tous les caractères du source d'un fichier, y compris les caractères spéciaux qui n'apparaissent pas à l'affichage ?
    Il suffit de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for line in fichier:
    print [line]
    Attention, c'est [line], et non pas line.
    En voyant TOUS les caractères, on peut désormais faire des programmes qui vont se déplacer dans un fichier en maitrisant complétement ces déplacements.






    Sans aller plus loin dans la compréhension des fichiers, je crois que ces simples réflexions sont utiles puisqu'elles permettent déjà de mieux comprendre certains points:

    - insérer du texte dans un fichier est une vue intellectuelle: sur le disque dur on ne peut pas couper un sillon, l'écarter, coller un nouveau morceau avec des bits inscrits dessus, recoller aux deux bouts et refermer tout ça ! Il va falloir comprendre les outils que sont les modes 'r','a','r+','a+'. J'y ai passé des heures.

    - «tu effaces le contenu »
    Effacer des bits, ça ne veut rien dire. La petite surface qui assure le support physique d'un bit ne peut pas disparaître et elle est toujours polarisée d'une façon ou d'un autre: soit 0 soit 1. Même le 0 est une polarisation donnée, ou une absence totale de polarisation, je n'en sais rien, EN TOUS CAS elle a un CERTAIN ÉTAT. Et si on ne dit pas au lecteur de disque qu'il ne doit pas lire cette petite surface, il va y passer dessus et il va en tirer une valeur de bit. En réalité quand il est question d'effacement de données sur un disque dur, il s'agit concrètement de mise hors de portée des bits supportant ces données, c'est à dire que la référence à ces bits est sortie de tel ou tel registre.

    - «ensuite tu colles le nouveau contenu»
    je ne comprends pas trop ce que ça veut dire, coller. Écraser des données en en réécrivant d'autres à la place, oui je comprends.
    Il faut comprendre ce que veut dire écrire dans un fichier, cela veut concrètement dire: on part d'un point précis situé sur un sillon du disque dur et on inscrit successivement des caractères, c'est à dire des octets, en avançant sur le sillon. Ceci se fait en écrasant
    les données qui se trouvent contenues dans les bits parourus: ça veut dire qu'on remplace une succession de valeurs de bits par une autre succession de valeurs de bits.

    Il faut savoir que, pour chaque fichier, il y a un pointeur de fichier qui se trouve toujours positionné à un endroit ou à un autre du fichier. Et que lorsq'on fait écrire des données à partir d'un point p du fichier, le pointeur suit l'écriture: une fois achevée l'écriture d'une séquence de données, le pointeur se trouve positionné juste aprés le dernier des caractères qui viennent d'être écrits. Il n'a aucune raison d'en partir si on ne le lui ordonne pas, et à la prochaine séquence d'écriture, l'inscription des données se fera en repartant précisément de cette position immédiatement après le dernier caractère.


    - La plupart du temps le système d'exploitation gère le positionnement de la pointe d'écriture tout seul parce qu'on n'a pas d'exigence sur cet aspect. Mais si on écrit un code pour manipuler des fichiers en réécriture, le code donne des instructions au système d'exploitation pour placer les caractères voulus relativement à ceux déja inscrits, parce que c'est le système d'exploitation qui est au courant des registres de où et où sont les données dans le disque dur.

    L'instruction de positionnement s'écrit avec la fonction seek(). Écrire f.seek(125) fait positionner le pointeur du fichier f devant le caractère indicé 125, c'est à dire le 126 ième caractère du fichier. La position 0 est le début du fichier. (Pour ma part, je me représente les positions comme pour les chaines de caractères: la position 2 c'est le point situé entre le caractèes d'indice 1 et le caractère d'indice 2, c'est à dire entre le 2ième et le 3ième caractères. Ce n'est pas réellement un point; c'est une représentation intellectuelle de ce qu'il y a entre deux caractères. Dans le fichier physique ce n'est rien. Dans certains tutoriels j'ai vu faire référence à cette notion sous l'appellation "zero-width")

    - Évidemment, pour utliser f.seek(p) il faut connaître la valeur de la position p. Elle peut être connue à priori, ou bien devoir être déterminée par programme.
    Pour des programme de ce genre, les fonctions tell(), flush(), fsync(), fileno() sont plus ou moins nécessaires.
    Tu trouveras des exemples de ce genre de programme ici:
    http://www.developpez.net/forums/d65...chier-mode-rp/


    ---------------------------



    Pour ce qui est d'un programme de modification d'un fichier en particulier:

    Il faut tenir compte du fait qu'il est possible qu'il y ait des balises ou des caractères spéciaux un peu partout dans le fichier source. Si on n'écrit un programme qu'en faisant des positionnements du pointeur par rapport aux caractères normalement affichables, on risque d'avoir des surprises.

    Par exemple si dans un fichier .txt, il y a
    'Vollum Institute and\\b Department of Microbiology\\b0 , Oregon Health & Science\\par\n'
    et qu'on fasse le remplacement de la portion de texte 'Microbilogy, Oregon' (visualisée sur écran) par 'Space Technolgies, New York', sans s'apercevoir qu'on fait disparaître ainsi une balise de cloture de mise en gras, on risque de se retrouver avec une erreur , ou du texte gras au delà de la limite initiale.

    Ces problèmes de balises sont variables d'un type de fichier à un autre.
    Je crois que c'est d'ailleurs l'origine des grosses difficultés posées par la transcription de fichiers écrits dans un type donné dans un autre type de fichier.
    Donc il faut regarder à chaque fois le code source du fichier en détail, et pour cela utiliser mon astuce donnée plus haut.



    ---------------------------



    Pour ce qui est de tes fichiers à toi,

    Comme dit plus haut, il n'y a pas besoin de faire un enregistrement préalable de la portion que j'ai appelée postp, puisqu'elle n'est formée que du seul caractère '}'.
    On met ce caractère directement aprés l'insert, tu l'as compris.
    Tu as aussi trouvé tout seul qu'il faut faire précéder insert de '\n' si on veut que insert soit écrit après un retour à la ligne.
    Il est est de même après insert si insert ne se termine pas naturellement par \n': il faut alors écrire '\n'+insert+'\n}'. Mais je ne crois pas que ce soit le cas, sinon tu l'aurais sans doute fait.

    Le problème de la mauvaise insertion que tu décris dans le message #4 est dû à l'erreur que j'avais commise dans mon code: '{' au lieu de '}'.
    Le dernier '{' rencontré était celui de {Ici je test les caracteres}
    Cependant, dans ce cas, il y a quelque chose de non-compréhensible: la deuxième ligne du texte obtenu texte obtenu devrait être
    Ligne 2 de mon fichier de configuration ici je mets le contenu de mon fichier ligne 1
    et non pas
    configuratioici je mets

    Maintenant que tu vas avoir mon astuce d'affichage intégral, tu vas pouvoir faire une analyse de ce qui est contenu de façon affichable ET occulte dans les sources de tes fichiers. Et ça va devenir bien plus clair.
    Je viens de voir tes interventions, manifestement, il te manquait cette astuce de l'affichage intégral: sans elle, c'est comme vouloir faire un collier de perles multicolores en mettant les mains sous un drap.

    Il faut notamment regarder quels sont les caractères qui suivent ce qui est censé être le dernier caractère du fichier. On pourrait avoir des surprises.
    J'ai écrit mon code proposé en utilisant rfind() justement en pensant qu'on ne savait pas ce qui pouvait se cacher au delà de ce dernier caractère (je commence à avoir des réflexes de prudence).
    En effet, on pourrait imaginer une autre faon de faire: on mesure la longueur du fichier et on positionne le pointeur un caractre avant la fin, c'est à dire devant le dernier '}'.
    Mais j'ai bien fait de chosir rfind() parce que je me suis donc aperçu aujourd'hui qu'il y a effectivement plein de caractères dans un fichier .txt en plus de ceux que je connais dans les fichiers que j'utilise habituellement.
    On ne sait pas, tu vas peut être constater qu'il y a un ultime '}' occulte après celui qui s'affiche normalement en dernier. Suite au prochain épisode.


    --------


    Désolé pour la longueur de ce post.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Salut,

    Tout d'abord merci pour ta réponse. J'avais vu le message hier soir, mais je préférais le lire à tête reposé.
    Ton message m'a beaucoup aidé, certes je savais qu'un fichier était composé de 0 et de 1 mais j'avais oublié le fait que ce qui était affiché n'était pas forcément le contenu réel de mon fichier.
    Je vais relire ton post ainsi que le lien que tu m'as donné. Mais je pense surtout que c'est ton bout de code pour afficher un fichier qui va me servir. En effet, maintenant je comprends pourquoi mes caractères disparaissaient....enfin je vais déjà vérifier.
    En attendant je tenais à te remercier pour le temps passé à m'aider. Maintenant pour te remercier, il faut que j'arrive à finir ce petit programme!
    Merci à toi ;-)

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    J'ai essayé ta fameuse commande qui permet de lire 'la source' du fichier (abus de langage je sais...mais je pense que tu me comprends) : Ce qui est affiché à l'écran corresponds exactement à ce que ta commande me donne.

    Voici le résultat de mon prog :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    # fichier :C\MAJ\cfgserver.txt
    ici je mets le contenu de mon fichier ligne 1
    ici je mets le contenu de mon fichier ligne 2
    ici je mets le contenu de mon fichier ligne 3 
    ici je mets le contenu de mon fichier ligne 4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #Fichier C:\MonAppli\cfg\cfgserver.txt
    {
    un
    deux
    trois
    }
    Mais voici le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    {
    un
    deux
    tro
    ici je mets le contenu de mon fichier ligne 1
    ici je mets le contenu de mon fichier ligne 2
    ici je mets le contenu de mon fichier ligne 3 
    ici je mets le contenu de mon fichier ligne 4
    }
    Du coup je comprends pas! Je pensais qu'un caractère venait perturbé mon prog mais non .... ( Pourquoi j'ai deux caractères qui disparaissent ???

  11. #11
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut Je suis très déçu.
    Après 2 heures de recherche hier soir, je me suis aperçu que les fonctions find() et seek() ne comptent pas les déplacements dans une chaîne de la même façon.

    La différence se situe plus précisément au niveau de leur façon de prendre en compte le retour à la ligne:
    - pour tous les "binômes échappés" autres que '\n' c'est à dire '\a',\b','\f','\r','\t','\v','\x','\\' find() et seek() comptent de la même manière: ces binômes valent pour elles 1 caractère
    - pour le binôme échappé '\n':
    find() y compte 1 caractère
    seek() y compte 2 caractères !!

    Cette différence est mise en évidence par le programme suivant qu'il suffit d'appliquer au source d'un fichier texte comportant ces binômes échappés. Il faut regarder ce qui se passe au niveau des positions où se trouvent les '\n' dans la chaine du source.
    Ce programme devrait être suffisamment explicite par lui-même.
    Je l'ai essayé sur un fichier .txt et sur un fichier .rtf, et j'ai observé la conclusion ci-dessus. Je ne garantis pas que ce soit la même chose pour tous les formats de fichiers, je commence à êre très circonspect:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    f = open ('fichier.txt')
    ch = f.read()
    for i in xrange(len(ch)):
        q = ch[i:i+4]
        l = len(q)
        print 'len de q =',len(q),'    q = '+'ch['+str(i).rjust(3)+':'+str(i+4).rjust(3)+'] ='+(4-q.count('\\'))*' ',[q],
        print '\tch.find[q] = '+str(ch.find(ch[i:i+4])).rjust(3),
        f.seek(i)
        print '\tf.seek('+str(i)+').read()[0:4] =',[f.read()[0:4]]
    f.close()

    -------------------------------------


    Cette différence me déçoit beaucoup parce qu'elle entraine que les traitements de chaines avec déplacement controlé du pointeur de fichier dans un fichier sont rendus plus compliqués à piloter.

    Il faut noter une chose qui m'était un peu sortie de l'esprit:
    seek() n'est pas exactement une fonction qui positionne le pointeur à une position donnée. C'est une fonction qui lui fait subir un décalage (offset en anglais) à partir d'une position de référence.

    NB: offset n'a pas exactement le sens de 'décalage' en anglais, mais plutôt celui de 'contrepoids, contrebalancer'. Cependant j'ai remarqué qu'en informatique, le mot offset est employé en réalité pour cette notion de décalage. C'est mon avis.

    En tous cas, la véritable syntaxe de seek() est f.seek(n,pref) pour spécifier un décalage de n caractères (c'est l'offset) par rapport à la position de référence pref:
    n peut être positif ou négatif
    - une valeur pref de 0 signifie position de référence est le début du fichier ; n dans seek(n,0) est par conséquent l'indice absolu
    - une valeur pref de 1 signifie position actuelle du pointeur
    - une valeur pref de 2 signifie position de référence est la fin du fichier

    Le problème est donc, a cause de ce décompte spécial de '\n' par seek(), que si le pointeur de fichier passe sur des retours à la ligne '\n' lors d'un déplacement qui lui est commandé, il va compter un caractère de plus que find() pour chacune de ces rencontres
    et que donc s'il passe sur x groupes '\n', il ira en fait x caractères moins loin que ce qu'on attendait.
    Ainsi, le code suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ch = "ocean\norange amere\nderegulation\nfredonner\nsoupir"
     
    f = open('bj.txt','w')
    f.write(ch)
    f.close()
     
    f = open('bj.txt')
    ch = f.read()
    print 'ch = f.read() a partir de  0 =',[ch]
    p = ch.find('donner')
    print "ch.find('donner') =",p
    f.seek(p)
    print "     f.read() a partir de",p,"=",[f.read(p)]
    f.close()
    donne comme résultat

    ch = f.read() a partir de 0 = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    ch.find('donner') = 35
    f.read() a partir de 35 = ['fredonner\nsoupir']
    on obtient 35 pour ch.find('donner') mais 'fredonner' pour print f.read() parce que le pointeur passe sur 3 groupes '\n'.



    ---------------------------------------------------------------------


    Tout ceci étant dit, qu'en est-il de ton problème en particulier ?

    Je suis étonné que tu présentes les deux résultats suivants comme des affichages intégraux:

    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
     
    # fichier :C\MAJ\cfgserver.txt
    ici je mets le contenu de mon fichier ligne 1
    ici je mets le contenu de mon fichier ligne 2
    ici je mets le contenu de mon fichier ligne 3 
    ici je mets le contenu de mon fichier ligne 4
     
     
     
    #Fichier C:\MonAppli\cfg\cfgserver.txt
    {
    un
    deux
    trois
    }
    Des affichages intégraux devraient donner ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    # fichier :C\MAJ\cfgserver.txt
    ['ici je mets le contenu de mon fichier ligne 1\n']
    ['ici je mets le contenu de mon fichier ligne 2\n']
    ['ici je mets le contenu de mon fichier ligne 3\n']
    ['ici je mets le contenu de mon fichier ligne 4']
     
     
    #Fichier C:\MonAppli\cfg\cfgserver.txt
    ['{\n']
    ['un\n']
    ['deux\n']
    ['trois\n']
    ['}']
    Je pense que tu t'es trompé. Pour avoir un affichage intégral, il faut faire de ce qu'on veut afficher un élément d'une liste, donc le [mettre entre crochets].


    ------------


    Pour être bien sûr de maitriser de quoi je parle , j'ai écrit le code suivant pour présenter le code qui résoud ton problème:
    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
    f = open('configMAJ.txt','w')
    f.write('contenu 1\ncontenu 2\ncontenu 3\ncontenu 4')
    f.close()
     
     
     
    print "Premiere procedure, sans decompte des '\\n'\n"
     
    f = open('config.txt','w')
    f.write('{\nmiam\nconfig{ca}tu\n}end')
    f.close()
     
    f = open('config.txt')
    chav = f.read()
    print 'AVANT\n',[chav]
    print chav
    f.close()
     
    f = open('configMAJ.txt')
    insert = f.read()
    f.close()
     
    f = open('config.txt','r+')
    ch = f.read()
    p = ch.rfind('}')
    print "     Dernier caractere '}' a position",p
    print '\nINSERT\n',[insert]
    f.seek(p)
    f.write(insert+'\n}')
    f.close()
     
    f = open('config.txt')
    ch = f.read()
    print '\nAPRES\n',[ch]
    print '\nAFFICHAGE normal:'
    print ch
    f.close()
     
     
    #--------------------------------------------------------
    print '\n\n\n'
    print "Seconde procedure, avec decompte des '\\n'\n"
     
    f = open('config.txt','w')
    f.write('{\nmiam\nconfig{ca}tu\n}end')
    f.close()
     
    f = open('config.txt')
    chav = f.read()
    print 'AVANT\n',[chav]
    print chav
    f.close()
     
    f = open('configMAJ.txt')
    insert = f.read()
    f.close()
     
    f = open('config.txt','r+')
    ch = f.read()
    p = ch.rfind('}')
    x = ch[0:p].count('\n')
    print "     Dernier caractere '}' a position",p
    print "     Nombre de '\\n' entre 0 et",p,"=",x
    print '\nINSERT\n',[insert]
    f.seek(p+x)
    f.write(insert+'\n}')
    f.close()
     
    f = open('config.txt')
    ch = f.read()
    print '\nAPRES\n',[ch]
    print '\nAFFICHAGE normal:'
    print ch
    f.close()
    Il crée deux fichiers configMaj.txt et config.txt dont le premier sert à la mise à jour du second.
    Une premiere procedure est celle utilisee jusqu'a present.
    La seconde procedure résoud ton problème: elle ratrappe l'originalité de seek() en poussant le décalage opéré par cette fonction autant de fois un caractère plus loin qu'elle rencontre un groupe '\n' dans le déplacement du pointeur.

    Mais je n'aime pas ce bazar, ça oblige à une gymnastique mentale supplémentaire et qui sait à quels problèmes inédits cela peut donner lieu dans certains cas.


    Précision importante:

    en affichage intégral, quand il y a deux '\' qui se suivent, cela exprime en réalité un seul '\' dans la chaine lue. En fait l'affichage intégral affiche à l'écran les chaines comme on les écrit quand, inversement, on les écrit pour un programme;
    c'est à dire que '\' étant un caractère d'échappement dans les chaines, on écrit 'u\\ny' si on veut indiquer qu'il s'agit de 'u'+'\'+'n'+'y' et non pas de 'u'+retour a la ligne+'y.
    Je ne sais pas si je suis bien clair...
    Dans le premier code en haut de ce message, j'ai mis print 'len de q =',len(q) pour qu'on puisse constater que la longueur de q est toujours 4, que [q] soit égal à ['ning'] ou à ['ing\\'] ou ['ng\\p'] ou à ['r\n\\p']
    On voit d'ailleurs gràce à cette instruction des ['par\n'] de longueur 4 qui montrent que len() considère aussi que '\n' est de longueur 1.

    ------------------

    Voilà, désolé d'avoir été si long mais le problème était ardu et je remarque que personne ne s'est préenté pour résoudre le problème de façon plus courte.
    En réalité , pour ton cas particulier, il y une manière de faire en partant de la fin mais je n'ai pas encore écrit le code. Ce n'est pas long mais je préfère envoyer ça tout de suite. Ça arrivera un peu plus tard, et puis tu peux trouver toi même je pense.
    En tous cas, je suis déçu mais j'ai bien appris.

  12. #12
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f = open('configMAJ.txt','rb+')
    devrait résoudre ton problème avec seek().
    Je crois que cela n'arrive que sous MS windows.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fi = open('C:\MAJ\cfgserver.txt')
    insert = fi.read()
    fi.close()
     
    g = open('C:\MonAppli\cfg\cfgserver.txt','rb+')
    ch = g.read()
    p = ch.rfind('}')
    g.seek(p)
    g.write("\n"+insert + '}')
    g.close()

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Et ben, j'ai pas tout compris, mais je vais à novueau bien me concentrer sur ce que tu as dit!
    En tout cas, j'ai compris pourquoi il m'effaçait les caractères...
    J'analyse, je test et je reviens pour toi.

    Merci pour tout!!!

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par pierjean Voir le message
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f = open('configMAJ.txt','rb+')
    devrait résoudre ton problème avec seek().
    Je crois que cela n'arrive que sous MS windows.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fi = open('C:\MAJ\cfgserver.txt')
    insert = fi.read()
    fi.close()
     
    g = open('C:\MonAppli\cfg\cfgserver.txt','rb+')
    ch = g.read()
    p = ch.rfind('}')
    g.seek(p)
    g.write("\n"+insert + '}')
    g.close()
    SUPER MERCIIIIII Ton script marche!!!!

    Mais merci pour ton aide

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Bon merci à pierjan pour sa solution et un grand merci à eyquem pour son aide, sa patience et le temps passer à m'aider!!!!

  16. #16
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    Et comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    insert = open('C:\MAJ\cfgserver.txt').read()
     
    ch = open('C:\MonAppli\cfg\cfgserver.txt','r').read()
    p = ch.rfind('}')
    g=open('C:\MonAppli\cfg\cfgserver.txt','w')
    g.write(ch+"\n"+insert + '}')
    g.close()

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    L'autre fonctionnait, mais celui non. Il m'ajoute le fichier après le } tout en le conservant.
    Mais ne te fatigue plus...ta première solution fonctionne.
    Merci encore ;-)

  18. #18
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Le second code de pierjean (message #16) marche à condition d'éliminer le '}' dans ch
    et de ne pas mettre '\n' avant l'insert car la position p est juste devant le dernier '}' qui va sauter, donc après le retour à la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    g.write(ch[0:-1]+insert+'}')
     
    # au lieu de 
     
    g.write(ch+"\n"+insert+'}')

    Mais ce code est simplement une réécriture complète du fichier, avec ajout: la partie du début jusqu'à p est gardé identique mais néamoins réécrite.
    C'est une autre possibilité, pourquoi pas si le fichier est petit.

  19. #19
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    pierjean, merci pour ton intervention qui apporte une notion fondamentale à avoir.
    J'aimerais d'ailleurs savoir si tu as amené 'rb+' sur le tapis parce que tu y as pensé dans un éclair d'intuition ou si c'est en toute connaissance de cause de ce qui est sous-jacent.

    J'ai apporté une solution au problème avec f.seek(p+x) mais comme un palliatif à un truc vicieux dans le fonctionnement de Python sans comprendre réellement la mécanique sous-jacente, tandis qu'avec l'utilisation de 'rb' et 'rb+' on atteint à la pleine compréhension de cette mécanique.

    L'idée de travailler en binaire m'avait traversé l'esprit quand j'avais lu ça sur la fonction seek():
    « If the file is opened in text mode (without 'b'), only offsets returned by tell() are legal. Use of other offsets causes undefined behavior. »
    Mais je n'ai pas suivi cette idée parce que je ne suis pas habitué aux fichiers binaires et que j'ai voulu comprendre l'origine du problème tel qu'on l'avait d'abord rencontré.

    Ta remarque
    «Je crois que cela n'arrive que sous MS windows»
    m'a fait retourner sur ce sujet et je suis arrivé jusqu'au PEP 278
    http://www.python.org/dev/peps/pep-0278/
    et ensuite des tests utilisant 'rb' m'ont permis de comprendre que j''ai fait une erreur en concluant de tests insuffisants que seek() voit deux caractères dans '\n'.
    Tu parles d'une fadaise.

    Je n'avais pas le bon outil pour faire des tests valables.
    Le bon outil de lecture exhaustive de tous les caractères d'un fichier, c'est le mode 'rb' qui le fournit.


    Pour créer un fichier .txt, il y a plusieurs manières (je suis sous Windows):
    - Start/Programs/Accessoires/Notepad et remplir à la main
    - clic droit sur le bureau/New/Text Document et remplir à la main
    - un petit programme Python ( f.write('hameau\nvillage') )

    Dans tous les cas, si je compte le nombre de caractères du texte, même en comptant pour 1 le retour à la ligne dont je ne vois pas le code '\n', je tombe sur un nombre inférieur à la taille que me donne un clic Propriétés fait sur le fichier.
    Par exemple, pour un fichier dans lequel on écrit 'hameau\nvillage\nbourg', je compte 20 caractères (avec retours à la ligne) mais l'interrogation de Propriétés indique 22 octets.
    Je n'avais aucune explication de ce fait et je ne m'en préoccupais pas.

    En réalité, quand un tel fichier .txt est crée, des '\r' sont ajoutés devant les '\n'.
    Je suppose que c'est le système d'exploitation, Windows, qui décide de cet ajout.


    Ensuite, il y a un truc vicieux de Python. Même si on fait lire et afficher en intégral le contenu d'un fichier par un programme Python, c'est à dire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for line in f:
        print [line]
    les [line] ne présentent pas les '\r' pourtant présents dans le source du fichier.
    Pourquoi ?

    « The three major operating systems used today are Microsoft Windows, Apple’s Macintosh OS, and the various Unix derivatives. A minor irritation of cross- platform work is that these three platforms all use different characters to mark the ends of lines in text files. Unix uses the linefeed (ASCII character 10), MacOS uses the carriage return (ASCII character 13), and Windows uses a two-character sequence of a carriage return plus a newline.
    Python’s file objects can now support end of line conventions other than the one followed by the platform on which Python is running. Opening a file with the mode 'U' or 'rU' will open a file for reading in universal newline mode. All three line ending conventions will be translated to a '\n' in the strings returned by the various file methods such as read() and readline(). »

    "What’s New in Python 2.3"

    Cependant, ce qui est décrit pour le mode 'U' est vrai pour le mode 'r' aussi. Je ne sais pas pourquoi mais le fait est que quand on affiche, même en intégral, une chaine qui a reçu la lecture d'un fichier, tout type de line end est transformé en '\n' et on ne voit pas les '\r' pourtant présent dans le source du fichier.

    Comment peut on être sûr que des '\r' sont présents dans le source ?
    Grâce au mode de lecture 'rb' qui, lui, lit les '\r' dans une chaine de saisie d'un fichier.


    Ensuite, si on est en mode 'r' ou 'r+',
    find() lit une chaine dans laquelle il n'y a pas les '\r'
    seek() se déplace dans le source du fichier, dans lequel il y a ces '\r'.
    D'où la différence.
    Ce n'est pas une fantaisie de fonctionnement de seek() qui est cause.

    Par contre, si on est en mode de lecture 'rb' ou 'rb+', on fournit à find() une chaine qui comporte les '\r' que voit seek() dans le fichier, donc les deux fonctions sont à égalité.


    On peut comparer:

    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
    from __future__ import with_statement
    import sys
     
    ch = "ocean\norange amere\nderegulation\nfredonner\nsoupir"
    print "chaine mise en fichier en mode 'w' =",[ch]
    print 'len de chaine =',len(ch)
     
    with open('fich.txt','w') as f:
        f.write(ch)
    print 'size du fichier =',getsize('bmj.txt')
     
     
    with open('fich.txt','r') as f:
        ch = f.read()
        print "\nch = fichier lu en 'r' = f.read() a partir de  0 =",[ch]
        p = ch.find('donner')
        print "ch.find('donner') =",p
        f.seek(p)
        print "f.read() a partir de f.seek("+str(p)+") =",[f.read(p)]
    chaine mise en fichier en mode 'w' = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    len de chaine = 48
    size du fichier = 52

    ch = fichier lu en 'r' = f.read() a partir de 0 = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    ch.find('donner') = 35
    f.read() a partir de f.seek(35) = ['fredonner\nsoupir']

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    with open('fich.txt','w') as f:
     
    with open('fich.txt','rb') as f:
    chaine mise en fichier en mode 'w' = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    len de chaine = 48
    size du fichier = 52

    ch = fichier lu en 'rb' = f.read() a partir de 0 = ['ocean\r\norange amere\r\nderegulation\r\nfredonner\r\nsoupir']
    ch.find('donner') = 38
    f.read() a partir de f.seek(38) = ['donner\r\nsoupir']

    Dernière remarque:
    si on écrit en mode 'wb', Windows n'inscrit pas des '\r' ajoutés dans le fichier.

    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
    from __future__ import with_statement
    import sys
     
    ch = "ocean\norange amere\nderegulation\nfredonner\nsoupir"
    print "chaine mise en fichier en mode 'wb' =",[ch]
    print 'len de chaine =',len(ch)
     
    with open('fich.txt','wb') as f:
        f.write(ch)
    print 'size du fichier =',getsize('bmj.txt')
     
     
    with open('fich.txt','r') as f:
        ch = f.read()
        print "\nch = fichier lu en 'r' = f.read() a partir de  0 =",[ch]
        p = ch.find('donner')
        print "ch.find('donner') =",p
        f.seek(p)
        print "f.read() a partir de f.seek("+str(p)+") =",[f.read(p)]
    chaine mise en fichier en mode 'wb' = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    len de chaine = 48
    size du fichier = 52

    ch = fichier lu en 'r' = f.read() a partir de 0 = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    ch.find('donner') = 35
    f.read() a partir de f.seek(35) = ['donner\nsoupir']
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    with open('fich.txt','wb') as f:
     
    with open('fich.txt','rb') as f:
    chaine mise en fichier en mode 'wb' = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    len de chaine = 48
    size du fichier = 52

    ch = fichier lu en 'rb' = f.read() a partir de 0 = ['ocean\norange amere\nderegulation\nfredonner\nsoupir']
    ch.find('donner') = 35
    f.read() a partir de f.seek(35) = ['donner\nsoupir']
    --------------------------------------------------------

    Les codes que nous avons écrits jusqu'à présent comportent un défaut:
    ils ne vérifient pas que le dernier '}' est bien le dernier caractère du fichier: on ne sait jamais, il ne faudrait pas perdre des données par erreur à cause d'on ne sait quel bug.....

    Je propose donc le code suivant qui, je pense, clôt le sujet.
    La fonction seek(-1,2) recule le pointeur de 1 caractère à partir de la fin.
    Il n'y a plus besoin d'utiliser rfind()


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from __future__ import with_statement
     
    with open('C:\MAJ\cfgserver.txt','rb') as f:
        insert = f.read()
     
    with open('C:\MonAppli\cfg\cfgserver.txt','rb+') as f:
        ch = f.read()
        if ch[-1]=='}':
            f.seek(-1,2)
            f.write(insert+'\n}')

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Salut eyquem,

    Avec ton code proposé, si il y a des sauts de lignes après le '}' ça ne fonctionnera pas. Au début j'avais aussi pensé
    à utiliser un tel algorithme, mais je pense que recherche le caractère est peut être plus sûr.
    En tout cas merci, car tu es vraiment à fond toi, ça fait plaisir ))

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Copier coller d'un fichier vers un autre
    Par loloz27 dans le forum Excel
    Réponses: 2
    Dernier message: 02/02/2009, 17h40
  2. Réponses: 1
    Dernier message: 09/12/2008, 12h23
  3. boucle avec copier coller dans un fichier excel
    Par Chalu_C_Momo dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 20/11/2008, 16h45
  4. copier-coller d'un fichier
    Par laurentdepibrac dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 03/07/2007, 16h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo