Ben*_*ank 10 python eof stringio
我需要循环,直到我到达类似文件的对象的末尾,但我没有找到"明显的方法去做",这让我怀疑我忽略了一些东西,很明显.:-)
我有一个流(在这种情况下,它是一个StringIO对象,但我也对一般情况感到好奇)以"<length> <data>"格式存储未知数量的记录,例如:
data = StringIO("\x07\x00\x00\x00foobar\x00\x04\x00\x00\x00baz\x00")
Run Code Online (Sandbox Code Playgroud)
现在,我能想象的唯一清晰的方法就是使用(我认为是)一个初始化的循环,这看起来有点像非Pythonic:
len_name = data.read(4)
while len_name != "":
len_name = struct.unpack("<I", len_name)[0]
names.append(data.read(len_name))
len_name = data.read(4)
Run Code Online (Sandbox Code Playgroud)
在一个类似C语言,我只是坚持的read(4)中while的测试条款,但当然不会对Python的工作.有没有想过更好的方法来实现这个目标?
小智 27
您可以通过iter()与sentinel 组合迭代:
for block in iter(lambda: file_obj.read(4), ""):
use(block)
Run Code Online (Sandbox Code Playgroud)
小智 10
你有没有看到如何迭代文本文件中的行?
for line in file_obj:
use(line)
Run Code Online (Sandbox Code Playgroud)
您可以使用自己的生成器执行相同的操作:
def read_blocks(file_obj, size):
while True:
data = file_obj.read(size)
if not data:
break
yield data
for block in read_blocks(file_obj, 4):
use(block)
Run Code Online (Sandbox Code Playgroud)
也可以看看:
我更喜欢已经提到的基于迭代器的解决方案将其转换为for循环.直接写的另一个解决方案是Knuth的"循环半"
while 1:
len_name = data.read(4)
if not len_name:
break
names.append(data.read(len_name))
Run Code Online (Sandbox Code Playgroud)
您可以通过比较看到它如何轻松地升级到自己的生成器并用作for循环.