小编典典

在Windows中的Python文件上混合read()和write()

python

看来,一个write()紧跟在read()上打开的文件r+(或r+b)在Windows的权限不更新文件。

假设testfile.txt当前目录中有一个文件,其内容如下:

This is a test file.

我执行以下代码:

with open("testfile.txt", "r+b") as fd:
    print fd.read(4)
    fd.write("----")

我希望代码可以打印This并将文件内容更新为:

This----a test file.

至少在Linux上这可以正常工作。但是,当我在Windows上运行它时,该消息会正确显示,但文件没有更改-
就像write()被忽略了一样。如果我tell()在文件句柄上调用它,则表明位置已更新(4write()和之前和8之后),但文件没有更改。

但是,如果我fd.seek(4)在该write()行的前面放了一个明确的名称,那么一切都会按照我的预期工作。

有人知道Windows下这种行为的原因吗?

供参考,我在Windows NT 7分区上使用Python 2.7.3。

编辑

在回应的意见,我都尝试r+brb+-的官方Python文档似乎意味着前者是规范的。

fd.flush()在各个地方拨打了电话,并在read()和之间放置了一个电话,write()如下所示:

with open("testfile.txt", "r+b") as fd:
    print fd.read(4)
    fd.flush()
    fd.write("----")

…产生以下有趣的错误:

IOError: [Errno 0] Error

编辑2

间接地,加入的flush()帮助,因为它使我这个帖子描述了类似的问题。如果对此发表评论的人之一是正确的,那是底层Windows C库中的错误。


阅读 225

收藏
2020-12-20

共1个答案

小编典典

Python的文件操作应遵循libc约定,因为它是在内部使用C文件IO函数实现的。

fopen手册页cplusplus中的fopen页引用

对于允许追加输入和输出操作而打开的要追加的文件(带有“
+”号的文件),应在写入操作和随后的写入操作之间对流进行刷新(fflush)或重新定位(fseek,fsetpos,rewind)。读取操作或未到达文件末尾的读取操作,然后进行写入操作。

总结一下,如果需要在写入后读取文件,则需要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;
}
2020-12-20