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 :

[Fichiers] Lire byte à byte


Sujet :

Python

  1. #1
    Invité
    Invité(e)
    Par défaut [Fichiers] Lire byte à byte
    Bonjour,

    J'ai un fichier dans lequel j'écris des nombres de 1 à 54. Plus tard dans mon programme, je veux accéder à nouveau à ce fichier afin d'y lire les nombres écrits. Je voudrais lire le fichier octets par octets afin de récupérer les nombres en entier, car pour le moment je récupère un 1 et un 7 à la place de 17.

    Voilà le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    f= open(getcwd()+'/clef.bk','r')
    i = 1
    while 1:
    	f.seek(i)
    	b = f.read(1)
    	if b == '':
    		break
    	if b != '':
    		print b
    	i+=1
    Edit : En fait, c'est surtout la façon dont j'écris les données qui pose problème en fait. Quand j'écris dans mon fichier, je voudrais écrire des int, et non pas des str(int). Comment faire en python ?
    Dernière modification par Invité ; 13/01/2010 à 09h48.

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    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,

    je ne comprends pas. ton fichier ressemble à ça:

    ou à ça:

    et c'est un fichier 'ascii' ou un fichier 'binaire' ? tu as écris le fichier avec:

    ou

    Si ton fichier ressemble au premier (et donc écrit en ascii), voici comment le lire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for line in open("toto",'r'):
        line = line.rstrip('\r\n')
        number = int(line)

  3. #3
    Invité
    Invité(e)
    Par défaut
    Non justement, je souhaite écrire tout à la suite, puis récupérer mes valeurs par la suite.

  4. #4
    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
    Il faut que tu essayes d’ouvrir en mode dit binaire: ’rb’

    Je ne sais pas en quoi consiste exactement ce mode. D’après ce que j’ai compris, ça force le système à lire vraiment caractère par caractère (c'est a dire octet pat octet ?). Je l’utilise pour analyser des textes, quand on veut pouvoir lire ce qu’il y a exactement dans un fichier. En effet, Python transforme automatiquement les fins de ligne ’\r\n’ en ’\n’ quand il en rencontre dans un texte. Être en mode ’rb’ permet d’obtenir vraiment ’\r\n’ dans la chaîne réceptrice de la lecture d’un fichier et de savoir donc où on en est exactement.

    Mais ça , ça concerne des fichiers de caractères.

    Pour un fichier dans lequels ont été enregistrés des nombres, je ne sais pas ce que ça donne d’utiliser ’rb’.

    Je ne sais d’ailleurs pas s’il est possible d’enregistrer des nombres sous une autre forme qu’en tant que caractères. Je pense que oui parce que je crois me rappeler qu’il y a eu une file il n’y a pas si longtemps qui a porté sur ce même problème d’analyse d’un fichier de nombres.
    C’est un sujet que je ne maîtrise pas.



    Peux tu nous fournir un tel fichier ? Qu’on essaie directement et voient ce que ça donne, stp



    Peux tu nous dire aussi comment tu crées ton fichier de nombres ?


    EDIT

    J’ai aussi l’impression que tu devrais aller voir du coté de la Data Persistence: pickle, cPickle, shelve, marshal, ...

    12.5. marshal
    This module contains functions that can read and write Python values in a binary format.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Hé bien justement, c'est tout le problème. Je voudrais à la fois créer ce fichier et le lire par la suite. Je peux facilement contourner le problème en méttant chaque nombre sur une ligne différent, donc mon problème n'en est pas vraiment un, mais je me suis posé la question du coup.

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2010
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2010
    Messages : 41
    Points : 40
    Points
    40
    Par défaut
    code vite fait mais sans complications
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    f = open('Fichier', 'r')
    ff = f.read()
    ff = ff.split(';') #en supposant que les nombres sont séparés par des ;
    # ff est maintenant une liste
    print ff[0]
    1

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bon changement de décor. j'ai un fichier, peu importe lequel, texte, image, video, peu importe. Je souhaite lire le fichier, mais octet par octet, et écrire dedans des octets et pas des valeurs. Je sais pas si je me fais bien comprendre ?

  8. #8
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    La lecture et l'écriture dans des fichiers binaires peut se faire sous forme de string Python, (méthodes read & write de l'objet file). La méthode seek peut être utile pour manipuler des fichiers binaires. Mais pour donner un sens à ces données, il faut les convertir en type de données Python. Les modules array et struct sont utiles pour cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> l = [1,2,3]
    >>> from array import array
    >>> array('B',l)    # B indique un encodage sous forme d'un octet non signé (unsigned char en C)
    array('B', [1, 2, 3])
    >>> array('B',l).tostring()
    '\x01\x02\x03'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> import struct
    >>> f = open('test.wav','rb')
    >>> RIFF_header = f.read(12)
    >>> RIFF_header
    'RIFF\x9e8\x03\x00WAVE'
    >>> struct.unpack('4sl4s', RIFF_header)
    ('RIFF', 211102, 'WAVE')

  9. #9
    Invité
    Invité(e)
    Par défaut
    Humm, je vois le potentiel mais je n'arrive pas à le mettre en place.

    En gros j'ai un fichier .jpg, je veux lire le fichier octet par octet pour pouvoir crypter le fichier en modifiant chaque octet individuellement, puis les retransformer par la suite (decryptage) pour les réinsérer dans un fichier.

    J'ai tenté ca mais bon :/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def Lire_Fic(self,chemin):
    		f = open(chemin, 'r')
    		cpt = 0
    		while 1:
    			f.seek(cpt)
    			s = f.read(1)
    			if s =='':
    				break
    			if s != '':
    				print str(struct.unpack('c',s))
    			cpt+=1
    		f.close()

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bon apparemment ca marche je récupère bien des octets sous forme de chaine, mais je n'arrive pas vraiment à en faire quelquechose. ('\xd9',) par exemple. Moi je voudrais transformer l'octet en int, faire une opération avec une clef de cryptage, puis faire l'operation inverse pour retrouver l'octet d'origine.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Ben euh si c'est que ça il suffit d'utiliser la fonction ord pour convertir en int (et puis la fonction inverse, chr, pour reconvertir en caractère). Tu n'as pas besoin de struct pour ça. Toutefois lire caractère par caractère c'est très lent, il vaut mieux lire (et écrire) par blocs de quelques milliers d'octets, voire tout le fichier en un coup s'il n'est pas trop gros.

    [EDIT]: Si le fichier n'est pas trop gros, mmap c'est sympa aussi ^^
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import mmap
     
    fn = 'test.dat'
    f = open(fn,'r+b')
    m = mmap.mmap(f.fileno(),0,access=mmap.ACCESS_WRITE)
    for i in xrange(len(m)):
        # exemple: inversion de tous les bits
        m[i] = chr(ord(m[i]) ^ 255)
    m.flush()
    m.close()
    f.close()

  12. #12
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 483
    Points : 9 282
    Points
    9 282
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà comment je ferais:

    Il faut d'abord une fonction de lecture-écriture de blocs de caractères. J'ai adapté pour cela ma fonction de copie de 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
     
    def traitementfichier(nfcs, nfcd, lgbuf=16384):
        """Traitement des octets d'un fichier et écriture du résultat dans un autre fichier"""
        fs = None
        fd = None
        try:
            fs = open(nfcs, 'rb')
            fd = open(nfcd, 'wb')
            while True:
                buf = fs.read(lgbuf)
                if buf=="":
                    break
                # ....
                # ici, traitement de buff qui est une chaine de lgbuf caractères
                # (ce traitement ne doit pas changer le nombre de caractères!!!)
                buf = traitementbuf(buf)  
                # ....
                fd.write(buf)
            fs.close()
            fd.close()
        except:
            if fs != None:
                fs.close()
            if fd != None:
                fd.close()
            raise IOError # relance l'erreur pour la transmettre a l'appelant
    Cette fonction lit des blocs 'buf' qui sont des chaines de caractères, appelle le traitement traitementbuf(buf). celui-ci transforme la chaine buf en liste d'octets, modifie les octets, et reconstitue à la fin la chaine (qui doit faire le même nombre de caractères). Cette chaine modifiée est écrite dans le fichier destination. Ceci jusqu'à la fin du fichier source (quand buf==""). On peut modifier à l'appel la taille du buffer (lgbuf=longueur de la chaine buf lue et écrite). Attention: le dernier buf lu n'a pas forcément la longueur lgbuf: ça dépend de la longueur totale du fichier!

    Pour le traitement des octets, j'ai pris ici l'exemple d'une rotation d'un bit à droite, avec réinjection du bit de droite à gauche de l'octet:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rotd = lambda b: (b>>1) | ((b&1)<<7)
    Par exemple,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    b = 92  => 01011100
    rotd(b) => 00101110
     
    b = 93 =>  01011101
    rotd(b) => 10101110
    Ce qui donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def traitementbuf(buf):
        bloc = [ord(c) for c in buf] # conversion de la chaine en liste d'octets
        # ....
        # ici, traitement des octets (= entiers de 0 à 255) de la liste bloc
        # par exemple: rotation à droite d'un bit de tous les octets
        bloc = [rotd(b) for b in bloc]
        # ....
        return ''.join([chr(b) for b in bloc])  # retour de la chaine modifiée
    Et voilà comment on utilise ça (exemple ici sous Windows):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    nfcs = r"C:\Users\Public\Documents\Wallpaper\FR-wp6.jpg"
    nfcd = r"C:\Users\Public\Documents\Wallpaper\FR-wp6_modif.jpg"
    try:
        traitementfichier(nfcs, nfcd)
    except IOError:
        print u"erreur de lecture/écriture"
    J'ai essayé sur le fichier FR-wp6.jpg (du Windows 7) qui fait 775832 octets et le traitement est rapide (dans la seconde).

    Tyrtamos

  13. #13
    Invité
    Invité(e)
    Par défaut
    Humm, ca m'a l'air assez complet, je vais essayer ça ! Merci beaucoup d'avoir planché sur le sujet !

    Siriru

Discussions similaires

  1. lire les bytes d'un fichier:ifstream vs FILE.
    Par alex.buisson dans le forum Langage
    Réponses: 6
    Dernier message: 21/03/2012, 15h06
  2. lire une fichier dans un byte[]
    Par azstar dans le forum C#
    Réponses: 10
    Dernier message: 05/08/2010, 16h41
  3. Lire les Bytes brut du protocole IP sur TCP
    Par Tleconte dans le forum Delphi
    Réponses: 1
    Dernier message: 21/05/2006, 02h32
  4. [PERL] lire un fichier bytes à bytes
    Par LE NEINDRE dans le forum Langage
    Réponses: 1
    Dernier message: 09/01/2006, 10h59
  5. [VB.NET] Fichier text et byte()
    Par nmerydem dans le forum Windows Forms
    Réponses: 6
    Dernier message: 10/11/2004, 17h28

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