引用documentation:
file.read([size])
最多从文件中读取 size 字节(如果读取达到 EOF 则更少在获取 size 字节之前)。如果 size 参数为负数或省略,则读取所有数据,直到达到 EOF。字节作为字符串对象返回。 当立即遇到 EOF 时返回一个空字符串。 (对于某些文件,如 ttys,在 EOF 被命中后继续读取是有意义的。)请注意,此方法可能会多次调用底层 C 函数 fread() 以获取尽可能接近 size 的字节。另请注意,在非阻塞模式下,即使没有给出大小参数,返回的数据也可能少于请求的数据。
这意味着(对于regular file):
-
f.read(1) 将返回一个字节对象,其中包含 1 字节或 0 字节是否达到 EOF
-
f.read(2) 将返回一个包含 2 个字节的字节对象,如果在第一个字节之后到达 EOF,则返回 1 个字节,如果立即遇到 EOF,则返回 0 个字节。
- ...
如果您想一次读取一个字节的文件,则必须在循环中 read(1) 并测试结果的“空性”:
# From answer by @Daniel
with open(filename, 'rb') as f:
while True:
b = f.read(1)
if not b:
# eof
break
do_something(b)
如果您想一次读取 50 个字节的“块”文件,则必须循环使用 read(50):
with open(filename, 'rb') as f:
while True:
b = f.read(50)
if not b:
# eof
break
do_something(b) # <- be prepared to handle a last chunk of length < 50
# if the file length *is not* a multiple of 50
事实上,您甚至可以更快地中断一次迭代:
with open(filename, 'rb') as f:
while True:
b = f.read(50)
do_something(b) # <- be prepared to handle a last chunk of size 0
# if the file length *is* a multiple of 50
# (incl. 0 byte-length file!)
# and be prepared to handle a last chunk of length < 50
# if the file length *is not* a multiple of 50
if len(b) < 50:
break
关于你问题的另一部分:
为什么容器 [..] 包含 [..] 一大堆 [bytes]?
参考that code:
for x in file:
i=i+1
print(x)
再次引用the doc:
文件对象是它自己的迭代器,[..]。当文件用作迭代器时,通常在 for 循环中(例如,for line in f: print line.strip()),next() 方法会被重复调用。此方法返回下一个输入行,或在打开文件以进行读取时遇到 EOF 时引发 StopIteration(打开文件以进行写入时行为未定义)。
上面的代码逐行读取一个二进制文件。即在每次出现 EOL 字符 (\n) 时停止。通常,这会导致不同长度的块,因为大多数二进制文件都包含随机分布的字符。
我不鼓励您以这种方式读取二进制文件。请选择基于read(size) 的解决方案。