5

在读取我的 GBK 编码文件时调用tell()会导致下一次调用readline()引发UnicodeDecodeError. 但是,如果我不打电话tell(),它不会引发此错误。

C:\tmp>hexdump badtell.txt

000000: 61 20 6B 0D 0A D2 BB B0-E3                       a k......

C:\tmp>类型 test.py

with open(r'c:\tmp\badtell.txt', "r", encoding='gbk') as f:
    while True:
        pos = f.tell()
        line = f.readline();
        if not line: break
        print(line)

C:\tmp>python test.py

a k

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    line = f.readline();
UnicodeDecodeError: 'gbk' codec can't decode byte 0xd2 in position 0:  incomplete multibyte sequence

当我删除该f.tell()语句时,它成功解码。为什么?我在Win7/Win10上试过Python3.4/3.5 x64,都一样。

任何一个,任何想法?我应该报告错误吗?

我有一个大文本文件,我真的很想得到这个大文本的文件位置范围,有解决方法吗?

4

2 回答 2

2

好的,有一个解决方法,它到目前为止有效:

with open(r'c:\tmp\badtell.txt', "rb") as f:
    while True:
        pos = f.tell()
        line = f.readline();
        if not line: break
        line = line.decode("gbk").strip('\n')
        print(line)

我昨天在这里提交了一个问题:http: //bugs.python.org/issue26990

仍然没有回应

于 2016-05-11T08:36:27.307 回答
2

我刚刚在 Linux 上的 Python 3.4 x64 上复制了这个。查看文档TextIOBase,我没有看到任何内容tell()会导致读取文件出现问题,所以它可能确实是一个错误。

b'\xd2'.decode('gbk')

给出与您看到的错误类似的错误,但在您的文件中,该 byte 后跟 byte BB,并且

b'\xd2\xbb'.decode('gbk')

给出等于 的值'\u4e00',而不是错误。

我找到了一种适用于您原始问题中的数据的解决方法,但不适用于其他数据,正如您后来发现的那样。希望我知道为什么!seek()我在 every 之后调用tell()tell()返回值:

pos = f.tell()
f.seek(pos)
line = f.readline()

另一种方法f.seek(f.tell())是使用 的SEEK_CUR模式seek()来给出位置。偏移量为 0,这与上面的代码相同:移动到当前位置并获取该位置。

pos = f.seek(0, io.SEEK_CUR)
line = f.readline()
于 2016-05-10T15:13:12.583 回答