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 :

Lecture améliorée fichier texte


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 45
    Points : 33
    Points
    33
    Par défaut Lecture améliorée fichier texte
    Bonjour à tous,

    Dans le cadre d'une automatisation, j'aurai besoin d'un script me permettant de faire la chose suivante: Trouver un mot dans le fichier, en déterminer la position, puis lire le mot d'avant.
    Plus précisément supposons un fichier comme celui ci:

    fdquh reazv re rvazevr rvzevrzeavrze rvzevrzea
    rvre rveazver vrzav verzvze vreazer rvzeavzer
    rveazverz vervazerv aervarzve aerveazr rvazevr
    fgsfdqs est la fdver errvezavr evrvazerv reazv
    rvezavr rveazvr erazvrv rezavrze rvzevze rvze

    dans ce cas, je devrai trouver la position du "la" pour ensuite déterminer ce qui le précède.

    J'ai commencé comme cela mais je n'arrive pas a trouver la position en ordonné dans la ligne puis à lire le mot d'avant !! De plus la fonction .tell() ne me retourne pas la bonne position du curseur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    chaine="la"
     
    fichier = open(fichier,'rb')
    for numeroLigne,ligne in enumerate(fichier.xreadlines())
      if(mot in ligne):
        print "trouve %s a la ligne %s" %(mot, numeroLigne)
        print fichierstream.tell()
        break
    Si vous savez d'ou vient ce problème.
    Merci beaucoup

  2. #2
    Membre habitué Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Points : 190
    Points
    190
    Par défaut
    Cherche du côté des expression régulières (librairie re).

    De mémoire, une exepression du genre "(\w) la " devrait te permettre d'isoler un mot qui précède le mot "la" lui même entre des espaces.

    Pour chaque ligne de ton fichier d'entrée, tu fais un re.find avec cette expression.

    --> si tu ne connais rien aux expressions régulières, sacrifie un peu de temps pour les découvrir : ça va changer ta vie !
    [WinXP sp3 / Visual 2005 / Eclipse Ganymede / Python 2.6]
    Hadrien

  3. #3
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    sinon simplement une fonction avec une méthode split, non?

    Enfin si tes fichiers sont toujours du type indiqué dans ton premier post.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def index(mot, fichier):
        fic=open(fichier, "r")
        ind=fic.read().split().index(mot)
        return ind
    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> index("la", "test.txt")
    19
    C'est juste pour l'index, car pour le reste, je ne comprend pas vraiment ce que tu veux faire.

    Si tu veux la phrase jusqu'au mot cherchant à indexer

    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
    class fichier(object):
        def __init__(self, fichier, mot):
            self.data=open(fichier, 'r').read().split()
            self.mot=mot
        def index(self):
            ind=self.data.index(self.mot)
            return ind
        def join(self):
            liste=[]
            for i in xrange(self.index()+1):
                liste.append(self.data[i])
            print " ".join(liste)
     
    f=fichier("test.txt", "la")
    f.join()
    Exemple :

    >>>
    fdquh reazv re rvazevr rvzevrzeavrze rvzevrzea rvre rveazver vrzav verzvze vreazer rvzeavzer rveazverz vervazerv aervarzve aerveazr rvazevr fgsfdqs est la
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  4. #4
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    bonjour,

    les gens au dessus on déja proposé un tas de solution, je réagis juste à:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    De plus la fonction .tell() ne me retourne pas la bonne position du curseur.
    si, elle retourne la bonne position mais la position du buffer de lecture. quand tu lis une ligne dans un fichier, Python lit en fait davantage d'information depuis le disque et les stocke en mémoire. Ca évite de faire des accès disque trop fréquents. tell renvoie la position dans le fichier par rapport à ce buffer. voilou.

  5. #5
    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
    Ni xreadlines() ni enumerate() n’ont de rapport avec le problème.

    xreadlines() parce que:

    file.xreadlines()
    This method returns the same thing as iter(file).
    New in version 2.1.
    Deprecated since version 2.3: Use for line in file instead.

    enumerate() parce que.


    Les deux programmes suivants donnent ainsi exactement le même résultat:

    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
    from os.path import getsize
    
    ch = """fdquh reazv re rvazevr rvzevrzeavrze rvzevrzea
    rvre rveazver vrzav verzvze vreazer rvzeavzer
    rveazverz vervazerv aervarzve aerveazr rvazevr
    fgsfdqs est la fdver errvezavr evrvazerv reazv
    rvezavr rveazvr erazvrv rezavrze rvzevze rvze"""
    
    with open('reazv.txt','wb') as fw:
      fw.write(ch)
    
    print "len de ch (y compris les \\n) : ", len(ch)
    print "taille du fichier reazv.txt  : ", getsize('reazv.txt')
    
    
    print '\n--------------------------------------------------------------------\n'
    
    
    with open('reazv.txt','rb') as fr:
    
      print "fr.tell() avant l'iteration :",fr.tell()
      print '''
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()'''
    
      mot,s = "la",0
      for numeroLigne,ligne in enumerate(fr.xreadlines()):
        s += len(ligne) 
        print "{:>11} {:>8} {:>10}".format(numeroLigne,s,fr.tell())    
        if(mot in ligne):
          print "\nj'ai trouve %s dans la ligne %s" % (mot, numeroLigne)
          break
    
    
    print '\n--------------------------------------------------------------------\n'
    
    
    with open('reazv.txt','rb') as fr:
    
      print "fr.tell() avant l'iteration :",fr.tell()
      print '''
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()'''
    
      mot,s,numeroLigne = "la",0,0
      for ligne in fr:
        s += len(ligne)
        print "{:>11} {:>8} {:>10}".format(numeroLigne,s,fr.tell())
        if(mot in ligne):
          print "\nj'ai trouve %s dans la ligne %s" % (mot, numeroLigne)
          break
        numeroLigne += 1

    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
    len de ch (y compris les \n) : 232
    taille du fichier reazv.txt  : 232
     
    --------------------------------------------------------------------
     
    fr.tell() avant l'iteration : 0
     
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()
              0       47        232
              1       93        232
              2      140        232
              3      187        232
     
    j'ai trouve la dans la ligne 3
     
    --------------------------------------------------------------------
     
    fr.tell() avant l'iteration : 0
     
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()
              0       47        232
              1       93        232
              2      140        232
              3      187        232
     
    j'ai trouve la dans la ligne 3

    Le fait que fr.tell() renvoie 232 (taille du fichier) dès le premier tour de l’itération, censé être la lecture de la première ligne, montre qu’en réalité, à ce stade, le fichier a déjà été lu en entier.

    Comme le dit kango, quand une instruction de lecture d’une ligne est exécutée, Python lit en fait davantage d’information sur le disque que ce qui est demandé.
    Cette information se retrouve dupliquée dans la mémoire cache du disque (qui fait aussi office de buffer dans l’autre sens) où elle sera plus rapidement accessible au prochain coup nécessaire (typiquement le cas dans une itération).

    Après une telle lecture, le pointeur de fichier ne se trouve donc pas au bout d’une ligne, mais au bout de la quantité d’information qui a été lue sur le disque pour remplir le cache.

    Pour un petit fichier, comme ci-dessus de 232 octets, le remplissage du cache se fait avec la lecture de la totalité du fichier et le pointeur se retrouve à la fin du fichier.



    Le code suivant montre 3 lectures/mises en cache pour lire 21 lignes dans un plus grand fichier:
    8192 octets (= 8 x 1024),
    puis 18432 - 8192 = 10240 octets ( = 10 x 1024),
    puis 21551 - 18432 = 3119 octets pour finir la lecture du 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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    morceaux = ('fdquh reazv re rvazevr rvzevrzeavrze rvzevrzea rvre rveazver gchhbgchc ',
                'vrzav verzvze vreazer rvzeavzer rveazverz verva  rvre rveazver hgx cbx ',
                'vrzav verzvze vreazer  rvre rveazver vrzav verzvze vreazer  rvre bzvcc ',
                'rveazver vrzav verzvze vreazer  rvre rveazver vrzav verzvze vreazer gf ',
                'zerv aervarzve aerveazr rvazev sfertty jhdtgytytrr fsreyuyww zfgtd64we ',
                'gdygfyete dggsgytytee hgfsda ettqwywtqw qwyqfwsqw qwgyqwtwdw dwdyuwgff ',
                'uywuwtwuyt uuwufuuiuh uggwyuyedy iyuygdcygwdecyg uhgcf kwgd uwudiwe gbd ',
                'ijsiciwdc lkohsudhc jhahgagc jhvaxufst hgvaxcqi hFASCI XXFUF jhcic tht4 ',
                'jhkoihqwqw 76247y2ed uwg8t8467g ucgwueyg uyeuwec63g jhsbckw6dcugu gfnfg ',
                'uhgcuyw vnavsyxtffduhv jhgvjd yhfytyd woii72 vyqtf7d2 duydug ugedd ndhh ',
                'iuhiqd jbj6 w77x b876t 88tn 887 n909u0 y87t67 g8t8 g88u8 tf5td7e hdyy7j ',
                'bskbcd hgvw hg34 uhg lpoe098 iuy73g ygdc7637 uyg7cct uygc76 uygc ugyyfg ',
                'jhwjgdf tytqywe25 bjhdgvgcue6t8343 khei jhiegy 5kjwiuc6 wlenoi99 foffih ',
                'hgfiwef ihi837t374f isdv8e873s xo 9 y9h 9i98ys 98y 98yjb u9 i9y 87yy98y ',
                'kjskjb jhbdg 8y9iube iwuiw6b iugiuw iwufiwfwf777u isuiwsued ig87w7 jhei ' )
     
    la_ligne = ''.join(morceaux) + '\n'
    print 'len de la_ligne =', len(la_ligne)
     
    with open('reazv2.txt','wb') as fw:
        fw.write(20*la_ligne)
        fw.write('ldc uhtftc lhfyuygbc kbygwygeed la kniweduiu nhdytd')
     
    with open('reazv2.txt','rb') as fr:
     
      print "\nfr.tell() avant l'iteration :", fr.tell()
      print '''
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()'''
     
      mot,s = "la",0
      for numeroLigne,ligne in enumerate(fr):
        s += len(ligne) 
        print "{:>11} {:>8} {:>10}".format(numeroLigne,s,fr.tell())
     
        if(mot in ligne):
          print "j'ai trouve %s dans la ligne %s" %(mot, numeroLigne)
          break
    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
    len de la_ligne = 1075
     
    fr.tell() avant l'iteration : 0
     
                   somme des
                   longueurs
      numeroLigne  de lignes   fr.tell()
              0     1075       8192
              1     2150       8192
              2     3225       8192
              3     4300       8192
              4     5375       8192
              5     6450       8192
              6     7525       8192
              7     8600      18432
              8     9675      18432
              9    10750      18432
             10    11825      18432
             11    12900      18432
             12    13975      18432
             13    15050      18432
             14    16125      18432
             15    17200      18432
             16    18275      18432
             17    19350      21551
             18    20425      21551
             19    21500      21551
             20    21551      21551
    j'ai trouve la dans la ligne 20


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


    Pour ce qui est de ton problème, il faut absolument cesser de penser un fichier comme composé de lignes.
    Un fichier est une chaîne de caractères parmi lesquels il y a des caractères de fins de ligne, c’est tout. La notion de ligne est une notion d’affichage qui ne nait que parce qu’un moteur de rendu interprète les fins de ligne pour produire un effet d’affichage.

    Mais dans certains algorithmes, la notion d'affichage de ligne n'a pas d'importance et on peut donc se passer de tenir compte des fins de lignes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    with open('reazv.txt','rb') as f:
        ch = f.read()
        x = ch.find(' la ')
        pre = ch[0:x].rfind(' ')
        mot_precedent = ch[pre+1:x]
        print 'mot precedent , de %s  caracteres:\n%s' % (len(mot_precedent),mot_precedent)


    Certes, il y a des cas spéciaux:
    - le mot est le premier, donc n’a pas de précédent
    - le mot précédent est dans la ligne précédente, c’est à dire qu’il y a un ’\n’ entre les deux mots
    - il y a plusieurs blancs ou autres caractères de type blanc entre les mots
    - il y a des caractères de type blanc à la fin d’une ligne
    - ou au début d’une ligne

    Et donc l’algorithme se complexifie:

    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
    ch = """fdquh reazvABCDEF re rvazevr rvzeABCDEFvrzeavrze rvzevrzea
    rvre rveazver vrzav verzvzeABCDEF vreazerABCDEF rvzeavzer
    rveazverz vervaABCDEF zerv\tXXDE aervarzve     aerveazrABCDEF rvazevr    \t
      \t FGSFDQS est la fdver er-ICI-rve ABCDEF zavr evrvazerv reazv
    ABCDEF rvezavr rveHazvr  \t wwHww    erazvrv rezavrze rvzevze rv-penultieme-ze FIN"""
     
    with open('reazvS.txt','wb') as fw:
      fw.write(ch)
     
    def mot_qui_precede(mot,ch):
        ch = ch + ' '
        if mot+' ' not in ch:
            return '\nLa suite de caracteres '+repr(mot+' ')+" n'a pas ete trouvee dans le texte."
        elif ch.strip()==mot:
            return "Il n'y a que le mot "+repr(mot)+" dans le texte."
        elif ch.lstrip().startswith(mot+' '):
            return '\nLe mot '+repr(mot)+" n'a pas de precedent car il est le premier."
        else:
            x = ch.find(mot)
            while (ch[x-1] not in (' ','\n') or ch[x+len(mot)] not in (' ','\n')):
                    y = ch[x+len(mot):].find(mot)
                    if y==-1:
                        return '\nLe mot isole '+repr(mot)+" n'a pas ete trouve dans le texte."
                    else:
                        x = x+len(mot) + y
            pre = ch[0:x-1].rstrip().rfind(' ')
            mot_precedent = ch[pre+1:x-1].rstrip()
            return '\nLe mot qui precede %s fait %s caracteres:\n%s'\
                  % (mot,len(mot_precedent),repr(mot_precedent))
     
     
    with open('reazvS.txt','rb') as f:
        ch = f.read()
        print mot_qui_precede('ABCDEF',ch)
        print mot_qui_precede('FGSFDQS',ch)
        print mot_qui_precede('FGXXXXXXQS',ch)
        print mot_qui_precede('fdquh',ch)
        print mot_qui_precede('XXDE',ch)
        print mot_qui_precede('FIN',ch)
        print mot_qui_precede('wwHww',ch)
    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
     
    Le mot qui precede ABCDEF fait 10 caracteres:
    'er-ICI-rve'
     
    Le mot qui precede FGSFDQS fait 7 caracteres:
    'rvazevr'
     
    La suite de caracteres 'FGXXXXXXQS ' n'a pas ete trouvee dans le texte.
     
    Le mot 'fdquh' n'a pas de precedent car il est le premier.
     
    Le mot isole 'XXDE' n'a pas ete trouve dans le texte.
     
    Le mot qui precede FIN fait 16 caracteres:
    'rv-penultieme-ze'
     
    Le mot qui precede wwHww fait 8 caracteres:
    'rveHazvr'

    Mais ce code ne comporte toujours pas de prise en compte des lignes en tant que lignes.

    À ce stade de complexité, on aura en effet peut être intérêt à passer à une utilisation des expressions régulières, comme le dit sopsag.
    Mais même avec expressions régulières, il ne sera pas nécessaire d’itérer sur des lignes, on traitera le fichier comme une chaîne d’un seul tenant.



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


    Bon à savoir aussi:


    - Lors d’une écriture dans un fichier sous Windows, cet OS écrit de sa seule initiative des fins de lignes ’\r\n’ même quand il ne rencontre que des ’\n’ dans le texte à écrire.
    Seul le mode ’wb’ , en binaire donc, assure de ce qu’on écrit dans un fichier.


    - Comme par ailleurs Python transforme en lecture tous les types de fins de lignes en seulement le caractère ’\n’ , on risque de passer longtemps avant de comprendre la cause de certains écarts entre la réalité et les résultats donnés par tell() sur un texte précisément connu dont on a fait l’écriture dans un fichier.
    http://www.python.org/dev/peps/pep-0278/

Discussions similaires

  1. Réponses: 2
    Dernier message: 08/11/2006, 20h57
  2. [C#]Lecture gros fichier texte
    Par kekesilo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 20/05/2006, 13h58
  3. Lecture d´un fichier texte .
    Par pilouface dans le forum C
    Réponses: 5
    Dernier message: 20/01/2006, 23h48
  4. [AS2] Lecture Ecriture Fichier Texte
    Par cpr0 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 13/09/2005, 11h22
  5. lecture de fichier texte
    Par prorider dans le forum C
    Réponses: 36
    Dernier message: 08/09/2004, 20h55

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