考虑这个非常简单的例子。
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()
关于python - encodings.utf_8.StreamReader readline(), read() 和 seek() 不合作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54349150/