看来,一个write()紧跟在read()上打开的文件r+(或r+b)在Windows的权限不更新文件。
write()
read()
r+
r+b
假设testfile.txt当前目录中有一个文件,其内容如下:
testfile.txt
This is a test file.
我执行以下代码:
with open("testfile.txt", "r+b") as fd: print fd.read(4) fd.write("----")
我希望代码可以打印This并将文件内容更新为:
This
This----a test file.
至少在Linux上这可以正常工作。但是,当我在Windows上运行它时,该消息会正确显示,但文件没有更改- 就像write()被忽略了一样。如果我tell()在文件句柄上调用它,则表明位置已更新(4在write()和之前和8之后),但文件没有更改。
tell()
4
8
但是,如果我fd.seek(4)在该write()行的前面放了一个明确的名称,那么一切都会按照我的预期工作。
fd.seek(4)
有人知道Windows下这种行为的原因吗?
供参考,我在Windows NT 7分区上使用Python 2.7.3。
编辑
在回应的意见,我都尝试r+b和rb+-的官方Python文档似乎意味着前者是规范的。
rb+
我fd.flush()在各个地方拨打了电话,并在read()和之间放置了一个电话,write()如下所示:
fd.flush()
with open("testfile.txt", "r+b") as fd: print fd.read(4) fd.flush() fd.write("----")
…产生以下有趣的错误:
IOError: [Errno 0] Error
编辑2
间接地,加入的flush()帮助,因为它使我这个帖子描述了类似的问题。如果对此发表评论的人之一是正确的,那是底层Windows C库中的错误。
flush()
Python的文件操作应遵循libc约定,因为它是在内部使用C文件IO函数实现的。
libc
从fopen手册页或cplusplus中的fopen页引用
对于允许追加输入和输出操作而打开的要追加的文件(带有“ +”号的文件),应在写入操作和随后的写入操作之间对流进行刷新(fflush)或重新定位(fseek,fsetpos,rewind)。读取操作或未到达文件末尾的读取操作,然后进行写入操作。
总结一下,如果需要在写入后读取文件,则需要fflush缓冲区,读取后的写入操作应以开头fseek,如fd.seek(0,os.SEEK_CUR)
fflush
fseek
fd.seek(0,os.SEEK_CUR)
因此,只需将您的代码段更改为
with open("test1.txt", "r+b") as fd: print fd.read(4) fd.seek(0, os.SEEK_CUR) fd.write("----")
该行为与类似的C程序的行为一致
#include <cstdio> int main() { char buffer[5] = {0}; FILE *fp = fopen("D:\\Temp\\test1.txt","rb+"); fread(buffer, sizeof(char), 4, fp); printf("%s\n", buffer); /*without fseek, file would not be updated*/ fseek(fp, 0, SEEK_CUR); fwrite("----",sizeof(char), 4, fp); fclose(fp); return 0; }