Python二进制文件EOF
我想要读取一个二进制文件。
我在网上搜索“python 二进制 文件结束符”,找到了这个链接。
现在,我有几个问题:
- 为什么容器(在SO回答中提到的x)里不是一个单独的字节,而是一大堆字节?我哪里做错了吗?
- 如果这样是正常的,我没有做错,那我该怎么读取一个单独的字节呢?也就是说,有没有办法在用
read(1)
方法读取文件时检测到文件结束符?
4 个回答
我做了以下事情。当调用read
时,如果遇到文件的结尾,它会返回一个“假”的值,这样就会结束循环。使用while ch != "":
虽然可以复制图像,但却导致了一个死循环。
from sys import argv
donor = argv[1]
recipient = argv[2]
# read from donor and write into recipient
# with statement ends, file gets closed
with open(donor, "rb") as fp_in:
with open(recipient, "wb") as fp_out:
ch = fp_in.read(1)
while ch:
fp_out.write(ch)
ch = fp_in.read(1)
逐字节读取:
with open(filename, 'rb') as f:
while True:
b = f.read(1)
if not b:
# eof
break
do_something(b)
""
表示文件的结束
with open(filename, 'rb') as f:
for ch in iter(lambda: f.read(1),""): # keep calling f.read(1) until end of the data
print ch
引用一下文档中的内容:
file.read([size])
从文件中最多读取size个字节(如果在读取过程中遇到文件结束符(EOF),可能会少于这个数量)。如果没有提供size参数或者它是负数,就会一直读取,直到遇到文件结束符为止。读取的字节会作为字符串返回。当立即遇到文件结束符时,会返回一个空字符串。(对于某些文件,比如终端文件,继续读取在遇到文件结束符后是有意义的。)请注意,这个方法可能会多次调用底层的C函数fread(),以尽量获取接近size字节的内容。另外,当处于非阻塞模式时,即使没有给size参数,返回的数据也可能少于请求的数量。
这意味着(对于一个常规文件):
f.read(1)
会返回一个字节对象,里面可能包含1个字节,或者如果遇到文件结束符则返回0个字节。f.read(2)
会返回一个字节对象,里面可能包含2个字节,或者如果在读取第一个字节后遇到文件结束符则返回1个字节,或者如果立即遇到文件结束符则返回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
关于你问题的另一部分:
为什么这个容器[..]包含了一大堆[字节]?
参考那段代码:
for x in file:
i=i+1
print(x)
再引用一下文档:
文件对象本身就是一个迭代器,[..]。当文件作为迭代器使用时,通常是在一个for循环中(例如,for line in f: print line.strip()),会重复调用next()方法。这个方法返回下一行输入,或者在遇到文件结束符时抛出StopIteration(当文件以写入模式打开时,行为是未定义的)。
上面的代码逐行读取一个二进制文件。它在每次遇到行结束符(\n
)时停止。通常,这会导致不同长度的块,因为大多数二进制文件中行结束符的出现是随机分布的。
我不建议你以这种方式读取二进制文件。请优先选择基于read(size)
的解决方案。