怎样在Python中一次读取文件中的一个字符?

98 投票
15 回答
209490 浏览
提问于 2025-04-15 23:39

在Python中,如果我有一个文件的名字,我该怎么写一个循环,让它每次读取一个字符呢?

15 个回答

16

我喜欢这个被接受的答案:它简单明了,能解决问题。我也想提供一个不同的实现方式:

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))

我建议的代码和你接受的答案基本上是同一个思路:从文件中读取一定数量的字节。不同的是,它首先读取一大块数据(对于X86来说,4006是个不错的默认值,但你也可以试试1024或8192;任何与你的页面大小相乘的数都可以),然后逐个返回这块数据中的字符。

我提供的代码在处理较大的文件时可能会更快。举个例子,托尔斯泰的《战争与和平》全文。这是我在测试时得到的结果(我在Mac Book Pro上使用OS X 10.7.4;so.py是我给这段代码起的名字):

$ 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

现在:不要把缓冲区大小4096当作绝对真理;看看我对不同大小的结果(缓冲区大小(字节)与实际时间(秒)):

   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 

如你所见,你可以更早地看到性能提升(而且我的时间测量可能不太准确);缓冲区大小是在性能和内存之间的权衡。默认的4096只是一个合理的选择,但一如既往,先进行测量。

44

首先,打开一个文件:

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

这段代码会逐行读取文件中的内容,然后再逐个查看每一行里的每一个字符。

111

在编程中,有时候我们会遇到一些问题,比如代码运行不正常或者出现错误。这种情况可能是因为我们没有正确理解某些概念或者使用了不合适的方式来解决问题。

例如,如果你在写代码时遇到了一些奇怪的错误,可能是因为你没有正确地使用变量,或者没有按照正确的顺序执行代码。这就像在做菜时,如果你把材料放错了地方,最后的菜可能就不好吃。

所以,遇到问题时,首先要冷静下来,仔细检查自己的代码,看看是否有地方可以改进。可以参考一些教程或者请教其他人,帮助自己更好地理解问题所在。

记住,编程是一个不断学习和实践的过程,遇到困难是很正常的,重要的是要保持耐心,逐步解决问题。

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

撰写回答