Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python encodings.utf_8.StreamReader readline()、read()和seek()don';不合作_Python_Python 3.x - Fatal编程技术网

Python encodings.utf_8.StreamReader readline()、read()和seek()don';不合作

Python encodings.utf_8.StreamReader readline()、read()和seek()don';不合作,python,python-3.x,Python,Python 3.x,考虑这个非常简单的例子 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

考虑这个非常简单的例子

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。

如果您只需交换代码,您的代码就可以工作

reader = codecs.getreader("UTF-8")
stream = reader(BytesIO(string))

编辑:如果您想使用StreamReader,可以使用
tell()
摆脱重新定位,因为
stream.read()
stream.readline()
足以重新定位。换句话说,使用当前代码,您将重新定位两次

循环中已更改的代码:

    # read first character
    char = stream.read(1)

    # end of stream
    if char == "":
        break

    # line is not comment
    if char != "#":
        lines.append(char + stream.readline())
        continue

    # line is comment. Skip it.
    stream.readline()

请注意对
行的更改。append()

如果您只需交换代码,则代码将正常工作

reader = codecs.getreader("UTF-8")
stream = reader(BytesIO(string))

编辑:如果您想使用StreamReader,可以使用
tell()
摆脱重新定位,因为
stream.read()
stream.readline()
足以重新定位。换句话说,使用当前代码,您将重新定位两次

循环中已更改的代码:

    # read first character
    char = stream.read(1)

    # end of stream
    if char == "":
        break

    # line is not comment
    if char != "#":
        lines.append(char + stream.readline())
        continue

    # line is comment. Skip it.
    stream.readline()

请注意对
行.append()的更改
您不想使用
编解码器
流读取器。它们是实现分层I/O以处理文本编码和解码的一种较旧、过时的尝试,因为它被更健壮、更快的实现所取代。已经有了

您确实希望将
编解码器.getreader()
的使用替换为:

此时,
while
循环起作用,
结束为
['Some line without comment\n']

您也不需要在此处使用seek或
tell()。您可以直接在文件对象(包括
TextIOWrapper()
对象)上循环:

甚至:

lines = [l for l in stream if not l.startswith('#')]
如果您担心
TextIOWrapper()
wrapper对象在不再需要包装器时关闭底层流,只需首先分离包装器:

stream.detach()

您不想使用
编解码器
流阅读器。它们是实现分层I/O以处理文本编码和解码的一种较旧、过时的尝试,因为它被更健壮、更快的实现所取代。已经有了

您确实希望将
编解码器.getreader()
的使用替换为:

此时,
while
循环起作用,
结束为
['Some line without comment\n']

您也不需要在此处使用seek或
tell()。您可以直接在文件对象(包括
TextIOWrapper()
对象)上循环:

甚至:

lines = [l for l in stream if not l.startswith('#')]
如果您担心
TextIOWrapper()
wrapper对象在不再需要包装器时关闭底层流,只需首先分离包装器:

stream.detach()

是的,没错,但使用reader很重要。这只是一个简单的例子-最小工作示例是的,这是真的,但使用reader很重要。这只是一个简单的示例-最小工作示例我建议始终先读取该行,然后检查结果字符串的第一个字符,以决定是否将该行附加到列表中。这似乎是一个错误。如果你坚持使用
StreamReader
,那么我鼓励你阅读整个政治公众人物,至少你会知道会发生什么。我的意见是写在墙上,你真的应该找到另一种方法。我建议你总是先读这行,然后检查结果字符串的第一个字符,以决定是否将这行附加到你的列表中。这似乎是一个错误。如果你坚持使用
StreamReader
,那么我鼓励你阅读整个政治公众人物,至少你会知道会发生什么。我的意见是,写东西是在墙上,你真的应该找到另一种方法。TextIOWrapper是一个伟大的解决方案,但我不能使用它,因为它的垃圾收集太早,它关闭了流@Joozty我认为您有更好的机会克服
TextIOWrapper
问题,而不是
StreamReader
问题。但是,如果没有看到您试图做的事情的实际例子,就很难提供有用的建议,问题中的代码似乎不是这样。@Joozty链接问题的公认答案解释了如何避免
TextIOWrapper
关闭流。如果这不能解决您的问题,您应该在问题中解释原因。@Joozty:您可以通过再次断开
TextIOWrapper
对象来避免这一问题;调用
stream.detach()。我给这个问题添加了一个答案,完全没有必要因为包装器超出范围而进行这些长度的测试。@Joozty:只是提醒一下:您链接的问题的OP现在已将我的答案标记为已接受。TextIOWrapper是一个很好的解决方案,但我不能使用它,因为它的垃圾收集太早,并且会关闭流@Joozty我认为您有更好的机会克服
TextIOWrapper
问题,而不是
StreamReader
问题。但是,如果没有看到您试图做的事情的实际例子,就很难提供有用的建议,问题中的代码似乎不是这样。@Joozty链接问题的公认答案解释了如何避免
TextIOWrapper
关闭流。如果这不能解决您的问题,您应该在问题中解释原因。@Joozty:您可以通过断开
Tex来避免这一问题