初学者Python:读取和写入同一个文件

Cry*_*sie 24 python io

一周前开始使用Python,我有一些关于阅读和写入相同文件的问题.我已经在线阅读了一些教程,但我仍然对此感到困惑.我可以理解简单的读写文件.

openFile = open("filepath", "r")
readFile = openFile.read()
print readFile 

openFile = open("filepath", "a")
appendFile = openFile.write("\nTest 123")

openFile.close()
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试以下操作,我会在写入的文本文件中收到一堆未知文本.任何人都可以解释为什么我会收到这样的错误,为什么我不能使用相同的openFile对象,如下所示.

# I get an error when I use the codes below:       
openFile = open("filepath", "r+")
writeFile = openFile.write("Test abc")

readFile = openFile.read()
print readFile

openFile.close()
Run Code Online (Sandbox Code Playgroud)

我会尽力澄清我的问题.在上面的示例中,openFile是用于打开文件的对象.如果我想第一次写它,我没有问题.如果我想使用相同的openFile来读取文件或附加内容.它不会发生或给出错误.在我可以对同一个文件执行另一个读/写操作之前,我必须声明相同/不同的打开文件对象.

#I have no problems if I do this:    
openFile = open("filepath", "r+")
writeFile = openFile.write("Test abc")

openFile2 = open("filepath", "r+")
readFile = openFile2.read()
print readFile

openFile.close()
Run Code Online (Sandbox Code Playgroud)

如果有人能告诉我这里做错了什么,或者只是一个Pythong的事情,我将不胜感激.我使用的是Python 2.7.谢谢!

sid*_*idi 22

更新回复:

这似乎是Windows特有的一个错误 - http://bugs.python.org/issue1521491.

引自http://mail.python.org/pipermail/python-bugs-list/2005-August/029886.html中解释的解决方法

除非在它们之间发生文件定位操作(例如,seek()),否则将读取与写入混合打开以进行更新的效果是完全未定义的.我猜不出你期望发生什么,但似乎很可能通过插入可靠地获得你想要的东西

fp.seek(fp.tell())

read()和write()之间.

我的原始回复演示了如何打开同一文件上的读/写以便附加作品.如果您使用Windows,显然不是这样.

原始回复:

在'r +'模式下,使用write方法将根据指针所在的位置将字符串对象写入文件.在您的情况下,它会将字符串"Test abc"附加到文件的开头.请参阅以下示例:

>>> f=open("a","r+")
>>> f.read()
'Test abc\nfasdfafasdfa\nsdfgsd\n'
>>> f.write("foooooooooooooo")
>>> f.close()
>>> f=open("a","r+")
>>> f.read()
'Test abc\nfasdfafasdfa\nsdfgsd\nfoooooooooooooo'
Run Code Online (Sandbox Code Playgroud)

字符串"foooooooooooooo"附加在文件的末尾,因为指针已经在文件的末尾.

您是否在一个区分二进制文件和文本文件的系统上?在这种情况下,您可能希望使用'rb +'作为模式.

将"b"附加到模式以在二进制模式下打开文件,在区分二进制文件和文本文件的系统上; 在没有这种区别的系统上,添加'b'没有效果. http://docs.python.org/2/library/functions.html#open


Car*_*roo 8

每个打开的文件都有一个隐式指针,指示数据的读写位置.通常,这默认为文件的开头,但如果使用a(append)模式,则默认为文件的结尾.同样值得注意的是,w即使您添加+到模式,该模式也会截断您的文件(即删除所有内容).

每当您读取或写入N个字符时,读/写指针将在文件中向前移动该数量.如果你还记得那些,我觉得把它想象成一个旧的盒式磁带是有帮助的.因此,如果您执行以下代码:

fd = open("testfile.txt", "w+")
fd.write("This is a test file.\n")
fd.close()

fd = open("testfile.txt", "r+")
print fd.read(4)
fd.write(" IS")
fd.close()
Run Code Online (Sandbox Code Playgroud)

...它应该最终打印This,然后将文件内容保留为This IS a test file..这是因为初始read(4)返回文件的前4个字符,因为指针位于文件的开头.它将指针留在后面的空格字符处This,因此下面write(" IS")用空格(与已存在的空格相同)覆盖接下来的三个字符IS,替换现有字符is.

您可以使用该seek()文件的方法跳转到特定点.在上面的示例之后,如果您执行了以下操作:

fd = open("testfile.txt", "r+")
fd.seek(10)
fd.write("TEST")
fd.close()
Run Code Online (Sandbox Code Playgroud)

...然后你会发现文件现在包含了This IS a TEST file..

所有这些都适用于Unix系统,您可以测试这些示例以确保.但是,我在混合read()write()Windows系统上遇到了问题.例如,当我在我的Windows机器上执行第一个示例时,它会正确打印This,但是当我之后检查文件时,它write()已被完全忽略.但是,第二个示例(使用seek())似乎在Windows上运行正常.

总之,如果你想从Windows中的文件中间读/写,我建议总是使用显式seek()而不是依赖于读/写指针的位置.如果你只做只读或只写,那么它是非常安全的.

最后一点 - 如果您在Windows上将路径指定为文字字符串,请记住转义反斜杠:

fd = open("C:\\Users\\johndoe\\Desktop\\testfile.txt", "r+")
Run Code Online (Sandbox Code Playgroud)

或者你可以r在开头使用原始字符串:

fd = open(r"C:\Users\johndoe\Desktop\testfile.txt", "r+")
Run Code Online (Sandbox Code Playgroud)

或者最便携的选择是使用os.path.join():

fd = open(os.path.join("C:\\", "Users", "johndoe", "Desktop", "testfile.txt"), "r+")
Run Code Online (Sandbox Code Playgroud)

您可以在官方Python文档中找到有关文件IO的更多信息.