考虑这个非常简单的例子。
import codecs
from io import BytesIO
string = b"""# test comment
Some line without comment
# another comment
"""
reader = codecs.getreader("UTF-8")
stream = reader(BytesIO(string))
lines = []
while True:
# get current position
position = stream.tell()
# read first character
char = stream.read(1)
# return cursor to start
stream.seek(position, 0)
# end of stream
if char == "":
break
# line is not comment
if char != "#":
lines.append(stream.readline())
continue
# line is comment. Skip it.
stream.readline()
print(lines)
assert lines == ["Some line without comment\n"]
我正在尝试从 StreamReader 逐行读取,如果该行以 # 开头,我将跳过它,否则我将其存储在列表中。但是当我使用 seek() 方法时有一些奇怪的行为。似乎 seek() 和 readline() 不合作并将光标移动到很远的地方。结果列表为空。
当然我可以用不同的方式来做。但正如我在上面所写,这是一个非常简单的示例,它可以帮助我理解事物是如何协同工作的。
我使用 Python 3.5。
请您参考如下方法:
您不想使用编解码器 流阅读器。自从被 io module 取代以来,它们是实现分层 I/O 以处理文本编码和解码的较旧、过时的尝试。 ,一个更健壮和更快的实现。已有serious calls for the stream readers to be deprecated .
您真的想用 io.TextIOWrapper() object 替换您对 codecs.getreader() 的使用:
import codecs
from io import BytesIO, TextIOWrapper
string = b"""# test comment
Some line without comment
# another comment
"""
stream = TextIOWrapper(BytesIO(string))
此时 while 循环起作用并且 lines 结束为 ['Some line without comment\n']。
您也不需要在此处使用搜索或 tell()。您可以直接在文件对象(包括 TextIOWrapper() 对象)上循环:
lines = []
for line in stream:
if not line.startswith('#'):
lines.append(line)
甚至:
lines = [l for l in stream if not l.startswith('#')]
如果您担心 TextIOWrapper() 包装器对象在您不再需要包装器时关闭底层流,只需先分离包装器:
stream.detach()
