Python stream.tell() 返回错误的位置

2 投票
1 回答
2224 浏览
提问于 2025-04-18 11:31

我试着用 tell() 方法来获取读取一行后光标的位置。感觉在 文本模式\r 的情况下有问题。我是用错了这个方法,还是说这是个bug呢?谢谢。

我在 python2.6、2.7 和 3.3 上测试过,结果都是一样的。

import io

with io.open('a', 'w') as fo:
    fo.write(u'abc\n')
    fo.write(u'def\r\n')
    fo.write(u'hij\r')
    fo.write(u'klm')

print('*io.open rb*')
with io.open('a', 'rb') as fo:
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))


print('*io.open rt*')
with io.open('a', 'rt') as fo:
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))
    print('--%r--%d' % (fo.readline(), fo.tell()))

输出:(不太确定 340282367000166625996085689099021713421 是什么)

*io.open rb*
--b'abc\n'--4
--b'def\r\n'--9
--b'hij\rklm'--16
--b''--16
*io.open rt*
--'abc\n'--4
--'def\n'--9
--'hij\n'--340282367000166625996085689099021713421
--'klm'--16

1 个回答

1

文本文件中有三种行结束符(EOL,表示行的结束):

  • Windows系统使用的是:\r\n
  • Unix(Linux)系统使用的是:\n
  • Mac系统使用的是:\r

你需要根据文件格式使用正确的行结束符。

  • 如果你想创建一个Unix格式的文件,可以用这个方法:io.open('a', 'w'),
  • 或者用这个方法也可以创建Unix格式的文件:io.open('a', 'wb'),
  • 而且不要使用'\r',因为它在Unix和Windows格式中都不适用:

Windows格式的文件:

            import io

            with io.open('a', 'w') as fo: #this will be a windows format file
                fo.write(u'abc\n')
                fo.write(u'def\n')
                fo.write(u'hij')
                fo.write(u'klm')


            print('*io.open rb*')
            with io.open('a', 'rb') as fo:
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))

            print('*io.open rt*')
            with io.open('a', 'rt') as fo:
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))

            >>>

            *io.open rb*
            --'abc\r\n'--5
            --'def\r\n'--10
            --'hijklm'--16
            --''--16

            *io.open rt*
            --u'abc\n'--5
            --u'def\n'--10
            --u'hijklm'--16
            --u''--16
            >>>

            import io

            with io.open('a', 'wb') as fo: #this will be a unix format file
                fo.write(u'abc\n')
                fo.write(u'def\n')
                fo.write(u'hij')
                fo.write(u'klm')

            print('*io.open rb*')
            with io.open('a', 'rb') as fo:
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))

            print('*io.open rt*')
            with io.open('a', 'rt') as fo:
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))
                print('--%r--%d' % (fo.readline(), fo.tell()))

            >>>
            *io.open rb*
            --'abc\n'--4
            --'def\n'--8
            --'hijklm'--14
            --''--14

            *io.open rt*
            --u'abc\n'--4
            --u'def\n'--8
            --u'hijklm'--14
            --u''--14
            >>>

正如你所看到的,结果总是一样的,没有那些奇怪的长数字。

撰写回答