简体   繁体   English

文件不写入当前文件位置

[英]file not write in current file position

with open('test.txt', 'w+') as f:
    f.write('foo')
    f.seek(0)
    f.read(1)
    print f.tell() # 1
    f.write('bar')

I want the result to be fbar but it returns foobar . 我希望结果是fbar但它返回foobar Obviously, file does not write at the current file position. 显然,文件不会写入当前文件位置。

with open('test.txt', 'w+') as f:
    f.write('foo')
    f.seek(0)
    f.read(1)
    m = f.tell() # 1
    f.seek(m)
    f.write('bar')

It works as I expect. 它像我期望的那样工作。

why do I need seek again while the current file position is already in 1 ? 为什么我需要在当前文件位置已经为1再次seek

this is caused by the fact that open returns a buffered file object. 这是因为open返回一个缓冲的文件对象。

When you're reading, it reads all the file behind the scenes because of buffering (because reading char by char from disk is inefficient). 当你正在阅读时,它会因为缓冲而读取幕后的所有文件(因为从磁盘读取char是低效的)。

f.tell() is coherent with what you've read, but internally when you write, the file pointer is somewhere else, that's why you have to workaround it by forcing the seek . f.tell()与你读过的内容是一致的,但是在你内部编写时,文件指针在其他地方,这就是你必须通过强制seek来解决它的原因。

That's only the "why?", but IMHO it's a bug (or a limitation), as write should/could use user-known position not internal system position of the underlying unbuffered file. 这只是“为什么?”,但恕我直言,这是一个错误(或限制),因为write应该/可能使用用户已知的位置而不是底层无缓冲文件的内部系统位置。

That's not a problem on read-only or write-only streams, but that's a problem in that interesting case. 这在只读或只写流上不是问题,但在这个有趣的情况下这是一个问题。

So now you know: to read after a write or write after a read , always use seek even if you think that the position of the file is correct. 所以现在你知道了:在readwritewriteread ,即使你认为文件的位置是正确的,也总是使用seek

As an alternative, you could use os.open to make sure buffering isn't involved (with some adaptations for the system calls as ftell doesn't exist, you have to seek 0 from current to get current pos): 作为替代方案,您可以使用os.open来确保不涉及缓冲(对于系统调用进行一些调整,因为ftell不存在,您必须从当前查找0以获取当前位置):

import os

f = os.open('test.txt',os.O_RDWR|os.O_TRUNC)
os.write(f,b'foo')   # b prefix needed, stream is binary
os.lseek(f, 0, os.SEEK_SET)
os.read(f,1)
# print(os.lseek(f, 0, os.SEEK_CUR)) # to seek/get current
os.write(f,b'bar')
os.close(f)

you get fbar all right in that case (even when disabling the lseek statement) 在这种情况下,你可以获得fbar (即使禁用lseek语句)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM