以二进制模式打开的BufferedReader迭代时为何能按行统计行数?
以二进制模式打开的BufferedReader迭代时为何能按行统计行数?
嗨,这个问题问得特别戳中要点,我刚接触Python文件操作的时候也有过一模一样的困惑!
先直接给你解惑:在Python里,不管是用文本模式还是二进制模式打开文件,当你直接迭代文件对象(比如你这里的handle,也就是_io.BufferedReader)时,默认的行为都是按“行”来读取内容的,只是两种模式下对“行”的定义和处理方式不一样而已。
你之前误以为二进制模式下会逐个字节返回,其实那是用handle.read(1)才会有的行为,而迭代文件对象是Python做了封装的便捷操作,专门用来按行处理的,不管模式如何。
具体来说:
- 文本模式(
'r'):会自动识别当前平台的换行符(比如Windows的\r\n、Linux/macOS的\n),把它们统一转换成\n,返回给你的是字符串类型的行内容。 - 二进制模式(
'rb'):不会做任何换行符的转换,完全按文件里的原始字节来判断“行”——只要遇到字节b'\n',就把从上次换行到当前的字节序列作为一行返回,返回的是bytes类型。
就拿你贴的这段代码来说:
with open("foo.txt", "rb") as handle: line_count = sum(1 for _ in handle)
这里迭代handle的时候,每次拿到的是一整行的字节(比如b'第一行内容\n'),所以sum(1 for _ in handle)自然就能统计出总行数——因为每迭代一次就对应一行,和文本模式下的行数统计结果是一致的(除非文件里有一些特殊的换行情况,但大部分场景下结果相同)。
Python这么设计其实是为了方便:就算是二进制文件,也可能存在用换行字节分隔的结构(比如某些二进制格式的日志、导出的二进制数据),直接按行迭代能省掉很多手动分割的麻烦。
如果真的需要逐个字节迭代,你可以用iter(lambda: handle.read(1), b'')这种写法,这时候才会每次返回一个字节的bytes对象。
备注:内容来源于stack exchange,提问作者jackal
相关产品推荐
相关产品推荐

