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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14271216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:56:37  来源:igfitidea点击:

Beginner Python: Reading and writing to the same file

pythonio

提问by Cryssie

Started Python a week ago and I have some questions to ask about reading and writing to the same files. I've gone through some tutorials online but I am still confused about it. I can understand simple read and write files.

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

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

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

openFile.close()

But, if I try the following I get a bunch of unknown text in the text file I am writing to. Can anyone explain why I am getting such errors and why I cannot use the same openFile object the way shown below.

但是,如果我尝试以下操作,我会在写入的文本文件中得到一堆未知文本。任何人都可以解释为什么我会收到这样的错误,以及为什么我不能以如下所示的方式使用相同的 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()

I will try to clarify my problems. In the example above, openFileis the object used to open file. I have no problems if I want write to it the first time. If I want to use the same openFileto read files or append something to it. It doesn't happen or an error is given. I have to declare the same/different open file object before I can perform another read/write action to the same file.

我会尽力澄清我的问题。在上面的例子中,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()

I will be grateful if anyone can tell me what I did wrong here or is it just a Pythong thing. I am using Python 2.7. Thanks!

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

采纳答案by sidi

Updated Response:

更新回复

This seems like a bug specific to Windows - http://bugs.python.org/issue1521491.

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

Quoting from the workaround explained at http://mail.python.org/pipermail/python-bugs-list/2005-August/029886.html

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

the effect of mixing reads with writes on a file open for update is entirely undefined unless a file-positioning operation occurs between them (for example, a seek()). I can't guess what you expect to happen, but seems most likely that what you intend could be obtained reliably by inserting

fp.seek(fp.tell())

除非在它们之间发生文件定位操作(例如,seek()),否则混合读取和写入对打开以进行更新的文件的影响是完全未定义的。我无法猜测您期望发生什么,但似乎很可能通过插入可以可靠地获得您的意图

fp.seek(fp.tell())

between read() and your write().

在 read() 和 write() 之间。

My original response demonstrates how reading/writing on the same file opened for appending works. It is apparently not true if you are using Windows.

我的原始回复演示了如何在打开以进行追加的同一文件上进行读/写。如果您使用的是 Windows,这显然不是真的。

Original Response:

原回复

In 'r+' mode, using write method will write the string object to the file based on where the pointer is. In your case, it will append the string "Test abc" to the start of the file. See an example below:

在 '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'

The string "foooooooooooooo" got appended at the end of the file since the pointer was already at the end of the file.

字符串“foooooooooooooo”被附加到文件的末尾,因为指针已经在文件的末尾。

Are you on a system that differentiates between binary and text files? You might want to use 'rb+' as a mode in that case.

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

Append 'b' to the mode to open the file in binary mode, on systems that differentiate between binary and text files; on systems that don't have this distinction, adding the 'b' has no effect. http://docs.python.org/2/library/functions.html#open

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

回答by Abhijit

Reading and Writing happens where the current file pointer is and it advances with each read/write. In your particular case, writing to the openFile, causes the file-pointer to point to the end of file. Trying to read from the end would result EOF. You need to reset the file pointer, to point to the beginning of the file before through seek(0)before reading from it

读取和写入发生在当前文件指针所在的位置,并且随着每次读取/写入而前进。在您的特定情况下,写入openFile, 会导致文件指针指向文件末尾。试图从最后读取会导致 EOF。您需要重置文件指针,seek(0)在读取之前指向文件的开头

回答by Cartroo

Every open file has an implicit pointer which indicates where data will be read and written. Normally this defaults to the start of the file, but if you use a mode of a(append) then it defaults to the end of the file. It's also worth noting that the wmode will truncate your file (i.e. delete all the contents) even if you add +to the mode.

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

Whenever you read or write N characters, the read/write pointer will move forward that amount within the file. I find it helps to think of this like an old cassette tape, if you remember those. So, if you executed the following code:

每当您读取或写入 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()

... It should end up printing Thisand then leaving the file content as This IS a test file.. This is because the initial read(4)returns the first 4 characters of the file, because the pointer is at the start of the file. It leaves the pointer at the space character just after This, so the following write(" IS")overwrites the next three characters with a space (the same as is already there) followed by IS, replacing the existing is.

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

You can use the seek()method of the file to jump to a specific point. After the example above, if you executed the following:

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

fd = open("testfile.txt", "r+")
fd.seek(10)
fd.write("TEST")
fd.close()

... Then you'll find that the file now contains This IS a TEST file..

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

All this applies on Unix systems, and you can test those examples to make sure. However, I've had problems mixing read()and write()on Windows systems. For example, when I execute that first example on my Windows machine then it correctly prints This, but when I check the file afterwards the write()has been completely ignored. However, the second example (using seek()) seems to work fine on Windows.

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

In summary, if you want to read/write from the middle of a file in Windows I'd suggest always using an explicit seek()instead of relying on the position of the read/write pointer. If you're doing only reads or only writes then it's pretty safe.

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

One final point - if you're specifying paths on Windows as literal strings, remember to escape your backslashes:

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

fd = open("C:\Users\johndoe\Desktop\testfile.txt", "r+")

Or you can use raw strings by putting an rat the start:

或者您可以通过r在开头放置一个来使用原始字符串:

fd = open(r"C:\Users\johndoe\Desktop\testfile.txt", "r+")

Or the most portable option is to use os.path.join():

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

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

You can find more information about file IO in the official Python docs.

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

回答by adambogdan1993

You can read, modify and save to the same file in python but you have actually to replace the whole content in file, and to call before updating file content:

您可以在 python 中读取、修改和保存到同一个文件,但实际上您必须替换文件中的整个内容,并在更新文件内容之前调用:

# set the pointer to the beginning of the file in order to rewrite the content
edit_file.seek(0)

I needed a function to go through all subdirectories of folder and edit content of the files based on some criteria, if it helps:

我需要一个函数来遍历文件夹的所有子目录并根据某些条件编辑文件的内容,如果有帮助的话:

new_file_content = ""
for directories, subdirectories, files in os.walk(folder_path):
    for file_name in files:
        file_path = os.path.join(directories, file_name)
        # open file for reading and writing
        with io.open(file_path, "r+", encoding="utf-8") as edit_file:
            for current_line in edit_file:
                if condition in current_line:
                    # update current line
                    current_line = current_line.replace('john', 'Hyman')
                new_file_content += current_line
            # set the pointer to the beginning of the file in order to rewrite the content
            edit_file.seek(0)
            # delete actual file content
            edit_file.truncate()
            # rewrite updated file content
            edit_file.write(new_file_content)
            # empties new content in order to set for next iteration
            new_file_content = ""
            edit_file.close()