Question Comment lire un seul caractère à la fois dans un fichier en Python?


Quelqu'un peut-il me dire comment puis-je faire cela?


47
2018-06-07 09:11


origine


Réponses:


with open(filename) as f:
  while True:
    c = f.read(1)
    if not c:
      print "End of file"
      break
    print "Read a character:", c

64
2018-06-07 09:19



ouvrez d'abord un fichier:

with open("filename") as fileobj:
    for line in fileobj:  
       for ch in line: 
           print ch

24
2017-12-25 17:52



J'aime la réponse acceptée: c'est simple et le travail sera fait. Je voudrais également proposer une mise en œuvre alternative:

def chunks(filename, buffer_size=4096):
    """Reads `filename` in chunks of `buffer_size` bytes and yields each chunk
    until no more characters can be read; the last chunk will most likely have
    less than `buffer_size` bytes.

    :param str filename: Path to the file
    :param int buffer_size: Buffer size, in bytes (default is 4096)
    :return: Yields chunks of `buffer_size` size until exhausting the file
    :rtype: str

    """
    with open(filename, "rb") as fp:
        chunk = fp.read(buffer_size)
        while chunk:
            yield chunk
            chunk = fp.read(buffer_size)

def chars(filename, buffersize=4096):
    """Yields the contents of file `filename` character-by-character. Warning:
    will only work for encodings where one character is encoded as one byte.

    :param str filename: Path to the file
    :param int buffer_size: Buffer size for the underlying chunks,
    in bytes (default is 4096)
    :return: Yields the contents of `filename` character-by-character.
    :rtype: char

    """
    for chunk in chunks(filename, buffersize):
        for char in chunk:
            yield char

def main(buffersize, filenames):
    """Reads several files character by character and redirects their contents
    to `/dev/null`.

    """
    for filename in filenames:
        with open("/dev/null", "wb") as fp:
            for char in chars(filename, buffersize):
                fp.write(char)

if __name__ == "__main__":
    # Try reading several files varying the buffer size
    import sys
    buffersize = int(sys.argv[1])
    filenames  = sys.argv[2:]
    sys.exit(main(buffersize, filenames))

Le code que je suggère est essentiellement la même que votre réponse acceptée: lisez un nombre donné d’octets dans le fichier. La différence réside dans le fait qu’elle lit tout d’abord une bonne partie des données (4006 est une bonne valeur par défaut pour X86, mais vous pouvez essayer le 1024 ou le 8192; un multiple de la taille de votre page), puis les caractères par un.

Le code que je présente peut être plus rapide pour les fichiers plus volumineux. Prends pour exemple, le texte entier de Guerre et Paix, par Tolstoï. Voici mes résultats (Mac Book Pro sous OS X 10.7.4; so.py est le nom que j'ai donné au code que j'ai collé):

$ time python so.py 1 2600.txt.utf-8
python so.py 1 2600.txt.utf-8  3.79s user 0.01s system 99% cpu 3.808 total
$ time python so.py 4096 2600.txt.utf-8
python so.py 4096 2600.txt.utf-8  1.31s user 0.01s system 99% cpu 1.318 total

Maintenant: ne prenez pas la taille du tampon à 4096 comme une vérité universelle; Examinez les résultats obtenus pour différentes tailles (taille de la mémoire tampon (octets) vs temps de la paroi (sec)):

   2 2.726 
   4 1.948 
   8 1.693 
  16 1.534 
  32 1.525 
  64 1.398 
 128 1.432 
 256 1.377 
 512 1.347 
1024 1.442 
2048 1.316 
4096 1.318 

Comme vous pouvez le voir, vous pouvez commencer à voir des gains plus tôt (et mes délais sont probablement très imprécis); la taille de la mémoire tampon est un compromis entre performance et mémoire. La valeur par défaut de 4096 est juste un choix raisonnable mais, comme toujours, mesurez d'abord.


13
2017-10-06 02:20



Python lui-même peut vous aider avec ceci, en mode interactif:

>>> help(file.read)
Help on method_descriptor:

read(...)
    read([size]) -> read at most size bytes, returned as a string.

    If the size argument is negative or omitted, read until EOF is reached.
    Notice that when in non-blocking mode, less data than what was requested
    may be returned, even if no size parameter was given.

8
2018-06-07 09:19



Juste:

myfile = open(filename)
onecaracter = myfile.read(1)

5
2018-06-07 09:21



J'ai appris un nouvel idiome pour cela aujourd'hui tout en regardant Raymond Hettinger Transformer le code en beau python idiomatique:

import functools

with open(filename) as f:
    f_read_ch = functools.partial(f.read, 1)
    for ch in iter(f_read_ch, ''):
        print 'Read a character:', repr(ch) 

4
2018-02-02 04:28



Il suffit de lire un seul caractère

f.read(1)

2
2018-06-07 09:19



Tu devrais essayer f.read(1), ce qui est certainement correct et la bonne chose à faire.


2
2018-06-07 09:19



f = open('hi.txt', 'w')
f.write('0123456789abcdef')
f.close()
f = open('hej.txt', 'r')
f.seek(12)
print f.read(1) # This will read just "c"

0
2018-02-25 22:28



Cela fonctionnera également:

with open("filename") as fileObj:
    for line in fileObj:  
        for ch in line:
            print(ch)

Il parcourt chaque ligne du fichier et chaque caractère de chaque ligne.


0
2017-12-01 19:29



Faire un supplément, Si vous lisez un fichier qui contient une ligne très volumineuse, ce qui pourrait vous briser la mémoire, vous pourriez envisager de les lire dans un tampon, puis de fournir chaque caractère.

def read_char(inputfile, buffersize=10240):
    with open(inputfile, 'r') as f:
        while True:
            buf = f.read(buffersize)
            if not buf:
                break
            for char in buf:
                yield char
        yield '' #handle the scene that the file is empty

if __name__ == "__main__":
    for word in read_char('./very_large_file.txt'):
        process(char)

0
2018-03-11 08:30