在Windows中的Python文件中混合使用read()和write() [英] Mixing read() and write() on Python files in Windows

查看:505
本文介绍了在Windows中的Python文件中混合使用read()和write()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来,在 read()之后的 write() Windows中的$ c> r + (或 r + b )权限不会更新文件。



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

 这是一个测试文件。 

我执行以下代码:

<$ p (testfile.txt,r + b)作为fd:
print fd.read(4)
$ - )

我希望代码打印这个并将文件内容更新为:

 这是一个测试文件。 

至少在Linux上可以正常工作。然而,当我在Windows上运行它,然后消息显示正确,但文件没有改变 - 这就像是被忽略的 write()。如果我在文件句柄上调用 tell(),它会显示位置已被更新( 4 > < c $ c> write()和 8 之后),但没有改变文件。



然而,如果我在 write()行之前放置一个明确的 fd.seek(4)那么一切都按我的预期工作。



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

作为参考,我在Windows 7上使用Python 2.7.3和NTFS分区。



编辑



为了回应评论,我尝试了 r + b rb + - 官方的Python文档似乎意味着前者是规范的。 / p>

我在不同的地方调用 fd.flush(),并在 read() write()类似于是:

 以open(testfile.txt,r + b)作为fd:
print fd .read(4)
fd.flush()
fd.write(----)

产生以下有趣的错误:

  IOError:[Errno 0] Error 

编辑2

间接地添加一个 flush()的帮助,因为它使我这篇文章描述了类似的问题。如果其中一个评论者是正确的,那么它就是底层Windows C库中的一个bug。

解析方案

libc 约定作为内部使用C文件IO函数来实现。



fopen手册页


对于打开附件的文件(包含+号的文件),在
上允许输入和输出操作,
之间的流应
被刷新(fflush)或重定位(fseek,fsetpos,rewind)操作或
读取操作,其中没有到达文件结尾,接着是
写入操作。



<总结一下,如果你需要阅读一个文件af在写入之前,您需要读取 fflush 缓冲区,并在读取之后执行写入操作,之后应该有一个 fseek code> fd.seek(0,os.SEEK_CUR)



所以,只要将你的程式码改为


$ b pre $ 打开(test1.txt,r + b)为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);
/ *没有fseek,文件不会被更新* /
fseek(fp,0,SEEK_CUR);
fwrite(----,sizeof(char),4,fp);
fclose(fp);
返回0;
}


It appears that a write() immediately following a read() on a file opened with r+ (or r+b) permissions in Windows doesn't update the file.

Assume there is a file testfile.txt in the current directory with the following contents:

This is a test file.

I execute the following code:

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

I would expect the code to print This and update the file contents to this:

This----a test file.

This works fine on at least Linux. However, when I run it on Windows then the message is displayed correctly, but the file isn't altered - it's like the write() is being ignored. If I call tell() on the filehandle it shows that the position has been updated (it's 4 before the write() and 8 afterwards), but no change to the file.

However, if I put an explicit fd.seek(4) just before the write() line then everything works as I'd expect.

Does anybody know the reason for this behaviour under Windows?

For reference I'm using Python 2.7.3 on Windows 7 with an NTFS partition.

EDIT

In response to comments, I tried both r+b and rb+ - the official Python docs seem to imply the former is canonical.

I put calls to fd.flush() in various places, and placing one between the read() and the write() like this:

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

... yields the following interesting error:

IOError: [Errno 0] Error

EDIT 2

Indirectly that addition of a flush() helped because it lead me to this post describing a similar problem. If one of the commenters on it is correct, it's a bug in the underlying Windows C library.

解决方案

Python's file operation should follow the libc convention as internally its implemented using C file IO functions.

Quoting from fopen man page or fopen page in cplusplus

For files open for appending (those which include a "+" sign), on which both input and output operations are allowed, the stream should be flushed (fflush) or repositioned (fseek, fsetpos, rewind) between either a writing operation followed by a reading operation or a reading operation which did not reach the end-of-file followed by a writing operation.

SO to summarize, if you need to read a file after writing, you need to fflush the buffer and a write operation after read should be preceded by a fseek, as fd.seek(0, os.SEEK_CUR)

So just change your code snippet to

with open("test1.txt", "r+b") as fd:
    print fd.read(4)
    fd.seek(0, os.SEEK_CUR)
    fd.write("----")

The behavior is consistent with how a similar C program would behave

#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;
}

这篇关于在Windows中的Python文件中混合使用read()和write()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆